NoImpLiveAny ফ্ল্যাগ সহ কোনও টাইপস্ক্রিপ্ট কম্পাইল করার সময় আমি কীভাবে "অবজেক্ট টাইপের সূচক স্বাক্ষরটিতে 'কোনও' টাইপ আছে” ত্রুটিটি রোধ করব?


309

আমি সর্বদা পতাকা - না ইম্পিলিটিউইনের সাথে টাইপস্ক্রিপ্ট সংকলন করি। আমি যেমন বুঝতে চাইছি আমার টাইপ চেকিং যতটা সম্ভব কড়া হোক।

আমার সমস্যাটি হ'ল নিম্নলিখিত কোড সহ আমি ত্রুটি পেয়েছি Index signature of object type implicitly has an 'any' type:

interface ISomeObject {
    firstKey:   string;
    secondKey:  string;
    thirdKey:   string;
}

let someObject: ISomeObject = {
    firstKey:   'firstValue',
    secondKey:  'secondValue',
    thirdKey:   'thirdValue'
};

let key: string = 'secondKey';

let secondValue: string = someObject[key];

লক্ষণীয় গুরুত্বপূর্ণ যে ধারণাটিটি হ'ল কী ভেরিয়েবলটি অ্যাপ্লিকেশনটির অন্য কোথাও থেকে আসে এবং এটি কোনও কী হতে পারে।

আমি স্পষ্টভাবে টাইপটি কাস্ট করার চেষ্টা করেছি:

let secondValue: string = <string>someObject[key];

বা আমার দৃশ্যের সাথে --noImplicitAnyকি ঠিক সম্ভব নয় ?

উত্তর:


337

একটি সূচক স্বাক্ষর যুক্ত করার ফলে টাইপস্ক্রিপ্টটি টাইপটি কী হওয়া উচিত তা জানতে দেয়।

আপনার ক্ষেত্রে যে হবে [key: string]: string;

interface ISomeObject {
    firstKey:      string;
    secondKey:     string;
    thirdKey:      string;
    [key: string]: string;
}

যাইহোক, এটি সূচি স্বাক্ষরের সাথে মেলে সমস্ত প্রকারের প্রকারের প্রয়োগ করে। যেহেতু সমস্ত সম্পত্তি stringএটির কাজ করে।

সূচী স্বাক্ষরগুলি অ্যারে এবং 'অভিধান' প্যাটার্ন বর্ণনা করার একটি শক্তিশালী উপায়, তারা আরও প্রয়োগ করে যে সমস্ত বৈশিষ্ট্য তাদের ফেরতের প্রকারের সাথে মেলে।

সম্পাদনা:

প্রকারগুলি যদি মেলে না, তবে ইউনিয়নের ধরণটি ব্যবহার করা যেতে পারে [key: string]: string|IOtherObject;

ইউনিয়ন প্রকারের সাথে, আপনি যদি টাইপস্ক্রিপ্টটিকে সংজ্ঞায়িত না করে প্রকারটিকে অনুমান করতে দেন তবে এটি আরও ভাল।

// Type of `secondValue` is `string|IOtherObject`
let secondValue = someObject[key];
// Type of `foo` is `string`
let foo = secondValue + '';

যদিও সূচক স্বাক্ষরে আপনার বিভিন্ন ধরণের থাকে তবে এটি কিছুটা অগোছালো হয়ে উঠতে পারে। তার বিকল্প হ'ল anyস্বাক্ষরে ব্যবহার করা। [key: string]: any;তারপরে আপনার উপরের মতো ধরণের কাস্ট করা প্রয়োজন।


এবং যদি আপনার ইন্টারফেসটি ইন্টারফেসের মতো দেখায় ISomeObject {প্রথম কে: স্ট্রিং; সেকেন্ডকি: আইওথরবজেক্ট; } এটা কি আমার অনুমান সম্ভব নয়?
জ্যাস্পার শুল্টে

ধন্যবাদ! প্রতি কেস কেটে প্রতি টাইপের কাস্টিংয়ের সাথে কোনও প্রকারের সংমিশ্রণটি বেচার উপায় বলে মনে হয়।
জ্যাস্পার শুল্টে

হাই, কীভাবে "যে কোনও অবজেক্ট [কী: অবজেক্ট] ['নাম']" পরিচালনা করবেন?
কোড_ক্রাশ

বা _obj = {} এর মতো কিছু বলুন; যাক _dbKey = _ ফসল [কী] ['নাম']; _obj [_dbKey] = এটি [কী]; এখানে _প্রসারণগুলি অবজেক্ট এবং অবজেক্ট [কী] এছাড়াও এমন একটি বস্তু ফিরিয়ে দেবে যার নাম সম্পত্তি থাকবে।
কোড_ক্রাশ

180

ত্রুটি এড়ানোর আরেকটি উপায় হ'ল কাস্ট ব্যবহার করা:

let secondValue: string = (<any>someObject)[key]; (প্রথম বন্ধনী নোট করুন)

কেবলমাত্র সমস্যাটি হ'ল এটি আর টাইপ-নিরাপদ নয়, যেমন আপনি কাস্ট করছেন any। তবে আপনি সর্বদা সঠিক ধরণের কাছে যেতে পারেন।

PS: আমি টাইপস্ক্রিপ্ট 1.7 ব্যবহার করছি, পূর্ববর্তী সংস্করণ সম্পর্কে নিশ্চিত নয়।


20
স্লিন্ট সতর্কতা এড়াতে, আপনি এগুলিও ব্যবহার করতে পারেন:let secondValue: string = (someObject as any)[key];
ব্রিওজেজে

96

টাইপস্ক্রিপ্ট ২.১ এই সমস্যাটি পরিচালনা করার জন্য মার্জিত উপায় প্রবর্তন করেছে।

const key: (keyof ISomeObject) = 'secondKey';
const secondValue: string = someObject[key];

আমরা keyofকীওয়ার্ড দ্বারা সংকলন পর্বের সময় সমস্ত অবজেক্টের সম্পত্তি নাম অ্যাক্সেস করতে পারি ( চেঞ্জলগ দেখুন )।

আপনার সাথে কেবল stringপরিবর্তনশীল প্রকারটি প্রতিস্থাপন করতে হবে keyof ISomeObject। এখন সংকলক জানে keyভেরিয়েবল কেবলমাত্র সম্পত্তি নাম থাকতে পারে ISomeObject

সম্পূর্ণ উদাহরণ:

interface ISomeObject {
    firstKey:   string;
    secondKey:  string;
    thirdKey:   number;
}

const someObject: ISomeObject = {
    firstKey:   'firstValue',
    secondKey:  'secondValue',
    thirdKey:   3
};

const key: (keyof ISomeObject) = 'secondKey';
const secondValue: string = someObject[key];

// You can mix types in interface, keyof will know which types you refer to.
const keyNumber: (keyof ISomeObject) = 'thirdKey';
const numberValue: number = someObject[keyNumber];

টাইপসক্রিপ্টআরং.আরজে লাইভ কোড (সেট noImplicitAnyবিকল্প)

সঙ্গে আরও পড়ুন আরো keyofব্যবহারগুলির


6
তবে যদি আমরা = 'দ্বিতীয়' + 'কী' keyহিসাবে ঘোষণা করি তবে এটি কার্যকর হবে নাconst key = (keyof ISomeObject)
হতাশ

55

নিম্নলিখিত tsconfig সেটিংস আপনাকে এই ত্রুটিগুলি উপেক্ষা করতে অনুমতি দেবে - এটিকে সত্য হিসাবে সেট করুন।

suppressImplicitAnyIndexErrors

সূচিপত্রের স্বাক্ষর নেই এমন বিষয়বস্তু সূচিকাগুলির জন্য কোনও ইম্পিলিকট্রুটি দমন করে।


14
এটি এমন কিছু যা আপনার করা উচিত নয় - সম্ভবত কোডটি আরও বুলেটপ্রুফ করার জন্য আপনার দলের কেউ স্পষ্টভাবে এই সংকলক বিকল্পটি সেট করেছেন!
atsu85

12
আমি এই মতটি ঠিক ঠিক এই বিকল্পটির জন্য তৈরি করা হয়েছে: ব্র্যাকেট স্বরলিপি দিয়ে অনুমতি দিন --noImplicitAny। পুরোপুরি অপের প্রশ্নটি ম্যাচ করুন।
ঘেটোলে

4
আমি @ গেটোলে সাথে একমত ইন্টারফেসটি সংশোধন করা সম্ভব না হলে এটিও একমাত্র বিকল্প। উদাহরণস্বরূপ, অভ্যন্তরীণ ইন্টারফেসের মতো XMLHttpRequest
মার্কো রায়

1
আমি @ গেটোলেতেও একমত আমি কৌতূহলী যে কীভাবে এটি পেড্রো ভিলা ভার্ডের উত্তরের চেয়ে কোডগতভাবে আলাদা (কোডটি কম কুশ্রী হওয়া বাদে)। আমরা সকলেই জানি যে যদি সম্ভব হয় তবে স্ট্রিং ব্যবহার করে কোনও বস্তুর সম্পত্তি অ্যাক্সেস করা এড়ানো উচিত, তবে ঝুঁকিগুলি বোঝার সময় আমরা কখনও কখনও সেই স্বাধীনতা উপভোগ করি।
স্টিফেন পল

এটি কেবল বাণিজ্য। আপনি যা পছন্দ করেন তা চয়ন করুন: ত্রুটিযুক্ত পৃষ্ঠের কম অঞ্চল এবং কঠোর সূচকের অ্যাক্সেস, বা ত্রুটির জন্য আরও পৃষ্ঠের ক্ষেত্র রয়েছে এবং সহজেই অজানা সূচকগুলিতে অ্যাক্সেস পান। টিএস 2.1 keyofঅপারেটর সবকিছুকে কঠোর রাখতে সহায়তা করতে পারে, পিয়োটারের উত্তর দেখুন!
trusktr

24

উপরে উল্লিখিত 'কীফ' সমাধানটি কাজ করে। তবে যদি ভেরিয়েবলটি একবার ব্যবহার করা হয় যেমন কোনও বস্তুর মাধ্যমে লুপিং ইত্যাদি, আপনি এটি টাইপকাস্টও করতে পারেন।

for (const key in someObject) {
    sampleObject[key] = someObject[key as keyof ISomeObject];
}

ধন্যবাদ। অন্য বস্তুর কীগুলি পুনরাবৃত্তি করার সময় এটি স্বেচ্ছাসেবী কী অ্যাক্সেসের জন্য কাজ করে।
বুকাবায়ে

18

ব্যবহার keyof typeof

const cat = {
    name: 'tuntun'
}

const key: string = 'name' 

cat[key as keyof typeof cat]

7

@ পাইওটর লেয়ান্ডোভস্কির উত্তরের মতো, তবে একটির মধ্যে forEach:

const config: MyConfig = { ... };

Object.keys(config)
  .forEach((key: keyof MyConfig) => {
    if (config[key]) {
      // ...
    }
  });

আপনি কীভাবে এটি কাজ করতে পেলেন? আমি একই জিনিস (TS 3.8.3) চেষ্টা করছি যদিও এটা বলার অপেক্ষা রাখে একটি ত্রুটি ছোঁড়া: Argument of type '(field: "id" | "url" | "name") => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'। আমার কোডটি দেখতে তেমন দেখাচ্ছে Object.keys(components).forEach((comp: Component) => {...}, যেখানে Componentপ্রকার (মত MyConfig)।
দ্য জিরাফিশ


6

কোন সূচক নেই? তারপরে নিজের করে নিন!

আমি বিশ্বব্যাপী এটি কোনও সামগ্রীর স্বাক্ষর সংজ্ঞায়নের সহজ উপায় হিসাবে সংজ্ঞায়িত করেছি। প্রয়োজনে Tহতে পারে any:

type Indexer<T> = { [ key: string ]: T };

আমি শুধু indexerক্লাস মেম্বার হিসাবে যুক্ত করি ।

indexer = this as unknown as Indexer<Fruit>;

সুতরাং আমি এটি দিয়ে শেষ:

constructor(private breakpointResponsiveService: FeatureBoxBreakpointResponsiveService) {

}

apple: Fruit<string>;
pear: Fruit<string>;

// just a reference to 'this' at runtime
indexer = this as unknown as Indexer<Fruit>;

something() {

    this.indexer['apple'] = ...    // typed as Fruit

এটি করার সুবিধা হ'ল আপনি যথাযথ প্রকারটি ফিরে পান - এমন অনেকগুলি সমাধান যা <any>আপনার জন্য টাইপিং হারাবে। মনে রাখবেন এটি কোনও রানটাইম যাচাই করে না। আপনি এখনও নিশ্চিত হন যে কিছু উপস্থিত রয়েছে কিনা তা আপনি অবশ্যই জেনে থাকবেন যে আপনি নিশ্চিতরূপে এটির অস্তিত্ব সম্পর্কে জানেন।

যদি আপনি অতিরিক্ত সতর্ক হতে চান এবং আপনি strictএকটি স্পষ্ট অনির্ধারিত চেক করার প্রয়োজন হতে পারে এমন সমস্ত জায়গাগুলি প্রকাশ করার জন্য আপনি এটি করতে পারেন:

type OptionalIndexed<T> = { [ key: string ]: T | undefined };

আমি সাধারণত এটি প্রয়োজনীয় খুঁজে পাই না কারণ আমার কোথাও থেকে স্ট্রিং সম্পত্তি হিসাবে থাকলে আমি সাধারণত জানি যে এটি বৈধ।

আমি এই পদ্ধতিটি বিশেষত দরকারী বলে মনে করি যদি আমার কাছে প্রচুর কোড থাকে যা সূচক অ্যাক্সেস করার প্রয়োজন হয় এবং টাইপিংটি কেবলমাত্র এক জায়গায় পরিবর্তন করা যায়।

দ্রষ্টব্য: আমি strictমোডটি ব্যবহার করছি এবং এটি unknownঅবশ্যই প্রয়োজনীয়।

সংকলিত কোডটি স্রেফ হবে indexer = this, সুতরাং টাইপসক্রিপটি যখন _this = thisআপনার জন্য তৈরি করে তবে এটির সাথে খুব মিল ।


1
কিছু ক্ষেত্রে আপনি এর Record<T>পরিবর্তে প্রকারটি ব্যবহার করতে সক্ষম হতে পারেন - আমি এই মুহুর্তের সূক্ষ্ম বিবরণ নিয়ে গবেষণা করতে এখনই সক্ষম নই তবে কিছু সীমিত ক্ষেত্রে এটি আরও ভাল কাজ করতে পারে।
সাইমন_উইভার

5

'সূচক' ইন্টারফেসটি সংজ্ঞায়িত করতে একটি ইন্টারফেস তৈরি করুন

তারপরে সেই সূচকটি দিয়ে আপনার অবজেক্টটি তৈরি করুন।

দ্রষ্টব্য: এতে প্রতিটি আইটেমের প্রকার প্রয়োগের ক্ষেত্রে অন্যান্য জবাবগুলি বর্ণিত একই প্রশ্নগুলির মধ্যে এখনও থাকবে - তবে এটি প্রায়শই আপনি চান।

আপনার যা প্রয়োজন জেনেরিক টাইপ প্যারামিটার তৈরি করতে পারেন: ObjectIndexer< Dog | Cat>

// this should be global somewhere, or you may already be 
// using a library that provides such a type
export interface ObjectIndexer<T> {
  [id: string]: T;
}

interface ISomeObject extends ObjectIndexer<string>
{
    firstKey:   string;
    secondKey:  string;
    thirdKey:   string;
}

let someObject: ISomeObject = {
    firstKey:   'firstValue',
    secondKey:  'secondValue',
    thirdKey:   'thirdValue'
};

let key: string = 'secondKey';

let secondValue: string = someObject[key];

টাইপস্ক্রিপ্ট খেলার মাঠ


জেনেরিক প্রকারের সংজ্ঞা দেওয়ার সময় আপনি এটিকে জেনেরিক সীমাবদ্ধতার মধ্যেও ব্যবহার করতে পারেন :

export class SmartFormGroup<T extends IndexableObject<any>> extends FormGroup

তারপরে Tক্লাসের ভিতরে ইনডেক্স করা যায় :-)


আমি সেখানে একটি প্রমিত 'বিল্ট-ইন' এর জন্য ইন্টারফেস মনে করি না Dictionaryযে প্রতিনিধিত্ব করে { [key: string]: T }, কিন্তু আমার মুছে ফেলার জন্য যদি সেখানে কি কখনো দয়া সম্পাদন করা এই প্রশ্ন হল ObjectIndexer
সাইমন_উইভার

3

এর কীটি স্ট্রিং এবং মানটি কোনও তা এই ধরণের দিয়ে বস্তুর ঘোষনা করুন এবং লিঙ্কটি প্রদর্শিত হবে না এমন প্রকারটি ঘোষণা করুন

type MyType = {[key: string]: any};

সুতরাং আপনার কোড হবে

type ISomeType = {[key: string]: any};

    let someObject: ISomeType = {
        firstKey:   'firstValue',
        secondKey:  'secondValue',
        thirdKey:   'thirdValue'
    };

    let key: string = 'secondKey';

    let secondValue: string = someObject[key];

1

আজকের দিনে আরও ভাল সমাধান হ'ল প্রকারগুলি ঘোষণা করা। মত

enum SomeObjectKeys {
    firstKey = 'firstKey',
    secondKey = 'secondKey',
    thirdKey = 'thirdKey',
}

let someObject: Record<SomeObjectKeys, string> = {
    firstKey:   'firstValue',
    secondKey:  'secondValue',
    thirdKey:   'thirdValue',
};

let key: SomeObjectKeys = 'secondKey';

let secondValue: string = someObject[key];

1

3 ধাপে টাইপস্ক্রিপ্ট 3.1 ব্যবহার করে আমি যে সহজ সমাধানটি পেয়েছি তা হ'ল:

1) ইন্টারফেস করুন

interface IOriginal {
    original: { [key: string]: any }
}

2) একটি টাইপযুক্ত অনুলিপি তৈরি করুন

let copy: IOriginal = (original as any)[key];

3) যে কোনও জায়গায় ব্যবহার করুন (জেএসএক্স অন্তর্ভুক্ত)

<input customProp={copy} />
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.