簡體   English   中英

TypeScript 不安全地使用“任何”類型的表達式錯誤

[英]TypeScript Unsafe use of expression of type 'any' ERROR

我是 TypeScript 的新手,並將我的場景描述如下:

我有這樣的類型:

 type response = {
  totalQuantity: number;
  numberOfCatogory: number
  appleQuantity: number;
  bananaQuantity: number;
  pearQuantity: number;
};

每個單獨的水果數量都有驗證,在這種情況下是 appleQuantity、bananaQuantity 和 pearQuantity,這意味着我需要從響應中獲取每個單獨的水果數量。

所以我創建了一個字符串數組,它像這樣保存單個屬性鍵:
const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]

Function 邏輯如下:

for (const individualParameter of individualParameters) {
    let individualQuantity = response[individualParameter];
    ...
}

但是當我構建時,TSLint 在response[individualParameter]上拋出錯誤說

Unsafe use of expression of type 'any'

我認為這是因為響應無法識別字符串數組元素的類型?
我是 TypeScript 的新手,很好奇解決這個問題的好方法。

問題出在這一行: const individualParameters:string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]

根據individualParameters的類型定義,每個元素都是一個string 這意味着即使這個"foo"字符串也可以分配給類型string

因此,typescript 拒絕使用response[individualParameter]因為response是具有嚴格鍵的類型,而individualParameter可能是任何字符串。

為了使其工作,您可以使用const assertion

type response = {
  totalQuantity: number;
  numberOfCatogory: number
  appleQuantity: number;
  bananaQuantity: number;
  pearQuantity: number;
};

const individualParameters = ["appleQuantity", "bananaQuantity", "pearQuantity"] as const

declare const response: response;

for (const individualParameter of individualParameters) {
  let individualQuantity = response[individualParameter]; // ok

}

如果您不喜歡as const方法,可以使用額外的 function:

type response = {
  totalQuantity: number;
  numberOfCatogory: number
  appleQuantity: number;
  bananaQuantity: number;
  pearQuantity: number;
};


declare const response: response;

const iterator = <
  Obj extends Record<string, number>,
  Keys extends Array<keyof Obj>
>(record: Obj, keys: Keys) => {
  for (const individualParameter of keys) {
    let individualQuantity = record[individualParameter];
  }
}

iterator(response, ['foo']) // expected error

// works only with literal array
iterator(response, ["appleQuantity", "bananaQuantity", "pearQuantity"]) // ok

操場

Obj - 表示response參數, Keys - 確保第二個數組參數由有效的Obj鍵組成

PS 根據 TS 約定,類型應該大寫。

所以我認為大多數人已經解釋了發生了什么,我認為到目前為止我個人最喜歡的答案是船長-yossarian 的答案 他很好地解釋了這個問題:

因此,typescript 拒絕使用 response[individualParameter] 因為 response 是具有嚴格鍵的類型,而 individualParameter 可能是任何字符串。

但是,可以通過告訴 Typescript 您正在定義一個包含字符串的數組來輕松解決此問題,這些字符串也是您嘗試訪問的類型的鍵:

type response = {
  totalQuantity: number;
  numberOfCatogory: number
  appleQuantity: number;
  bananaQuantity: number;
  pearQuantity: number;
};

// this should be your non-null and defined object in reality
let response: response;

// just this one line below was altered
const individualParameters: (keyof response)[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];

for (const individualParameter of individualParameters) {
    let individualQuantity = response[individualParameter];
}

類型(keyof response)[]意味着您將始終擁有一個僅包含response類型鍵的數組。 在我的示例中,此聲明是多余的,因為編譯器已經可以推斷出您定義的所有屬性都是該類型的鍵,但是當 for 循環位於 function 中時,情況就不同了。 我假設你就是這種情況,否則你不會在第一種情況下問這個問題。

@captain-yossarian 是對的; 根據 TS 約定,類型應該大寫。

您需要使您的響應可索引。 更多信息可以在這里找到。

在您的情況下,可以通過使用如下接口來完成:

interface IResponse {
  [key: string]: number;  // <- This line makes your interface indexable
  totalQuantity: number;
  numberOfCatogory: number
  appleQuantity: number;
  bananaQuantity: number;
  pearQuantity: number;
}

現在你只需要確保你的響應實現了 IResponse 接口:

const response: IResponse = {
  totalQuantity: 1,
  numberOfCatogory: 2,
  appleQuantity: 3,
  bananaQuantity: 4,
  pearQuantity: 5
}

在此之后,您可以使用字符串數組來獲取單個水果數量,如下所示:

const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];

for (let individualParameter of individualParameters) {
    console.log(response[individualParameter]);
}

// Output:
// 3
// 4
// 5

一種簡單的方法是您可以選擇將類型的鍵設為字符串變量

type response  = {
    [key: string]: number;
};

但是,如果您真的要修復 key 為 appleQuantity、 bananaQuantity 、blablabla,您可以嘗試Mapped Type ,點擊此鏈接了解更多詳情

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM