考慮這個函式:
function fn<T>(a: T, b: T[]): T {}
我希望它從 推斷T,然后a檢查b。T相反,TS 是從 和 推斷出來T的。例如:ab
fn(1, [1, 'str']);
這回傳number | string。但是,我想T被推斷為number,因此這會引發類似“數字 | 字串不可分配給數字”的錯誤。這可能嗎?
uj5u.com熱心網友回復:
您可以提供顯式型別:
declare function fnA<T>(a: T, b: (T extends T ? T : never)[]): T
fnA<number>(1, [2, 'str'])
// Type 'string' is not assignable to type 'number'.(2322)
或執行以下操作:
declare function fnB<T>(a: T, b: (T extends T ? T : never)[]): T
fnB(1, [1, 'str']);
// Type 'string' is not assignable to type '1'.(2322)
這迫使編譯器必須檢查型別a以找出b.
但這似乎推斷出比 更具體的型別number,所以這不起作用:
fnB(1, [1, 2]);
// Type '2' is not assignable to type '1'.(2322)
number我認為這打破了一些關于型別何時自動擴展為orstring以及何時不自動擴展的啟發式 Typescript 。打字稿很難知道約束該型別的嚴格程度。
但是,如果第一個引數是更廣泛的型別number,它會正常作業,例如:
const x: number = 1
fnB(x, [1, 2]); // fine
或者,如果您不喜歡它的推斷方式,您可以再次提供型別:
fnB<number>(1, [1, 2]); // fine
操場
uj5u.com熱心網友回復:
雖然這只是一個想法,但您也許可以使用 HOF
declare const fn = <T,>(a: T) => (b:T): T
fn(1)([1,'str'])
// Argument of type '(string | number)[]' is not assignable to parameter of type 'number'.ts(2345)
但是正如@alex 建議的那樣,只要您知道,最好提供顯式型別
uj5u.com熱心網友回復:
有一種替代方法:
type Primitives =
| string
| number
| bigint
| boolean
| symbol
| null
| undefined
type BackwardInference<T, P=Primitives> =
P extends any ? T extends P ? P : never : never;
declare function fn<T>(a: T, b: BackwardInference<T>[]): T
fn(1, [45]) // ok
fn('str', ['hello']) // ok
fn(42, ['str']) // expected error
操場
因為如果第一個引數是原始引數,TS 會推斷文字型別,我們可以稍微放松推斷嚴格性。這意味著當第一個引數是文字時42,第二個引數將被預期為number而不是42
uj5u.com熱心網友回復:
一種選擇是讓您的函式在推斷它們時采用兩個通用引數。通過這種方式,您可以輕松地將引數不是相互依賴的想法編碼,而是一個依賴于另一個。
主要的警告是,要同時使用文字和復雜型別,您需要擴展冗長的文字。
type WidenLiteral<T> =
T extends string ? string :
T extends number ? number :
T extends bigint ? bigint :
T extends boolean ? boolean :
T extends symbol ? symbol :
T;
function fn<T, U>(a: T, b: T extends U ? WidenLiteral<T>[] : never): T {
return a;
}
fn(1, [2,3,4]); // Valid
fn('foo', ['bar']); // Valid
fn(true, [false, true]); // Valid
fn({ foo: 42 }, [{ foo: 1 }, { foo: 2 }]); // Valid
fn(1, ['foo']); // Invalid
fn(false, [0]); // Invalid
fn({ foo: 42 }, [{ foo: "1" }, { foo: 2 }]); // Invalid
游樂場鏈接。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/482452.html
標籤:javascript 打字稿 打字稿泛型
