我有帶有硬編碼陣列值的物件。這個物件是as const因為在代碼的其他部分我需要 TS 來了解所有可能的值。
問題是我不能.every()在該物件的給定陣列上使用方法。TS 遵守關于This expression is not callable.即使該代碼作業得很好。
我在嘗試除錯時注意到了三件事:
- 相反的方法
some沒有問題。 - 如果我
as const從物件中洗掉,則沒有錯誤,every但就像我說的我不能洗掉它,因為 TS 需要了解所有值,而不是將它們視為任何值number - 如果我在該物件上使用硬編碼鍵而不是變數,它可以作業(但我需要將其用作函式)。
為什么這不起作用?我做錯了什么?
const demo = {
a: [44, 23, 77],
b: [22, 45, 55],
} as const
const everyfunction = (key: keyof typeof demo) => demo[key]
.every((value) => value > 40) // This expression is not callable.
const somefunction = (key: keyof typeof demo) => demo[key]
.some((value) => value > 40) // works
const everyfunction2 = () => demo['a']
.every((value) => value > 40) // works
console.log(somefunction('a'))
console.log(everyfunction('a'))
活生生的例子
uj5u.com熱心網友回復:
擴展的錯誤訊息提供了更多線索:
Each member of the union type '...' has signatures, but none of those signatures are compatible with each other.
那么為什么我們會得到這個錯誤,為什么不some產生相同的結果呢?我們需要在宣告檔案中Array查看這些方法的函式簽名實際上是什么:
every<S extends T>(
predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any
): this is S[];
every(
predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any
): boolean;
some(
predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any
): boolean;
如您所見,every有一個多載版本,而some沒有。的多載版本every充當型別謂詞,這意味著T傳入的陣列被斷言為型別S。這很有用,因為它允許我們執行以下操作:
const arr = ["a", "a", "a"]; // string[]
if (arr.every((char): char is "a" => char === "a")) {
const typedArr = arr; // "a"[]
}
你的例子中的問題是型別demo[key]是[44, 23, 77] | [22, 45, 55]. 這種型別觸發了 的多載版本every,為我們提供了兩個潛在的呼叫函式簽名:
<S extends [44, 23, 77]>(value: [44, 23, 77], index: number, array: T[]) => value is S
<S extends [22, 45, 55]>(value: [22, 45, 55], index: number, array: T[]) => value is S
everyTS 在編譯時無法知道使用這些簽名呼叫的結果- 它們不兼容,因為它們包含不同的數字文字。some另一方面,可以很好地呼叫,因為它沒有這樣的多載,而是創建了兩種型別的交集,44 | 23 | 77 & 22 | 45 | 55這使得簽名有效。
readonly number[]解決這個問題的最簡單方法是在呼叫之前將元組宣告為更寬的every:
const everyfunction = (key: keyof typeof demo) => (demo[key] as readonly number[])
.every((value) => value > 40)
您也許可以將其包裝在某種輔助函式中,以使用泛型來掩蓋斷言(此處提供的最低限度):
const everyOnObject = <O extends Record<string, readonly number[]>>(obj: O, key: keyof O) => {
return obj[key].every((value) => value > 40);
}
console.log(everyOnObject(demo, "a"));
uj5u.com熱心網友回復:
首先將您的物件結構定義為介面,您應該沒問題。
更新示例
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/454818.html
標籤:打字稿
上一篇:為什么這個Typescript錯誤“這個運算式不可呼叫”?
下一篇:擴展運算子-TypeScript
