خطای TypeScript TS7015 هنگام دسترسی به یک enum با استفاده از یک پارامتر نوع رشته


من تازهکار در TypeScript هستم و نمیفهمم برای رفع خطی که خطای TS7015 را ایجاد میکند (ارجاع به یک عضو enum با استفاده از یک متغیر رشتهای) چه کاری باید انجام دهم، زیرا خطی که بلافاصله پس از آن میآید خطا نمیدهد (ارجاع به یک عضو enum با استفاده از یک رشته ثابت):

enum State {
    Happy = 0,
    Sad = 1,
    Drunk = 2
}

function Emote(enumKey:string) {
    console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Happy"]); // no error
}

اگر "noImplicitAny": true در tsconfig.json پروژه تنظیم شده باشد، خطا شناسایی میشود

در فایل tsconfig.json پروژه، "noImplictAny": false تنظیم شده است و هیچ خطایی شناسایی نمیشود

من با "ntypescript": "^1.201603060104.1" کامپایل میکنم

من اکنون با "tsc": "1.8.10" در حال کامپایل هستم

C:>npm install -g typescript

`-- [email 

در حال بررسی نصب:

C:\>tsc --version

Version 1.8.10

این فایل tsconfig.json من است:

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "ES5",
    "module": "System",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": true,
    "noImplicitAny": true,
    "sourceMap": true,
    "mapRoot": "map/",
    "diagnostics": true
  },
  "exclude": [
    "node_modules",
    "typings"
  ]
}

این خروجی کامپایلر است:

C:\>tsc

test.ts(8,17): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

پاسخ شماره ۱

اگر از TypeScript 2.1 به بالا استفاده میکنید، میتوانید نوع enumKey را به keyof typeof State تغییر دهید، مانند این:

function Emote(enumKey: keyof typeof State) {...}

یا، اگر ورودی تابع لازم باشد که یک رشته باشد، این:

var state : State = State[enumKey as keyof typeof State];

توضیح:

به این دلیل که enumKey یک string دلخواه است، تایپاسکریپت نمیداند که آیا enumKey نام یکی از اعضای State است یا نه، بنابراین یک خطا تولید میکند. تایپاسکریپت ۲.۱ عملگر keyof را معرفی کرد که یک اتحاد از نامهای شناختهشده و عمومی ویژگیهای یک نوع بر میگرداند. استفاده از keyof به ما اجازه میدهد تأیید کنیم که این ویژگی واقعاً در شی هدف وجود دارد.

با این حال، زمانی که یک enum ایجاد میکنید، TypeScript در واقع هم یک نوع (که معمولاً یک زیرنوع از number است) و هم یک مقدار (شیء enum که میتوانید در عبارات به آن ارجاع دهید) تولید میکند. وقتی مینویسید keyof State، در واقع مجموعهای از اسامی ویژگیهای literal number را دریافت میکنید. برای دریافت اسامی ویژگیهای شیء enum به جای آن، میتوانید از keyof typeof State استفاده کنید.

منابع :

https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-compile-time

پاسخ شماره ۲

من مشکوکم که این مربوط به پشتیبانی جدید TS 1.8.x از رشتههای ثابت در این موقعیتها باشد. TS اتفاقی میداند که "Happy" یک اندیس رشتهای معتبر است، اما نمیداند آیا enumKey معتبر خواهد بود یا نه. شما میتوانید با تبدیل آن به <any>، آن را اصلاح کنید، به این شکل:

function Emote(enumKey:string) {
    console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Melancholy"]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Happy"]); // no error
    console.log(State[<any>enumKey]); // no error
    console.log(State[<any>"Melancholy"]); // no error
}

(راستی، فکر کنم این جدید است: من نتوانستم این خطا را با نسخه 1.8.9 دوباره ایجاد کنم، اما به محض اینکه به 1.8.10 ارتقا دادم، توانستم.)

جالب است که من انتظار داشتم این بدون خطا کار کند، اما اینطور نیست:

function TypedEmote(enumKey:'Happy'|'Sad'|'Drunk'){
    console.log(State[enumKey]);
}

حتماً چیزی در مورد مشخصات TS وجود دارد که من نمیفهمم، یا شاید آنها هنوز فرصت نکردهاند آن قسمت را درست کنند.