我正在嘗試為泛型函式創建多載,其中函式的回傳型別由作為“道具”提供給函式的物件上的屬性值確定。該函式有一個必需的泛型型別,它也用于回傳型別,盡管它對回傳的回傳型別沒有影響。
我不能添加另一個泛型型別,因為我要么必須手動定義它,要么如果我設定一個默認型別并在第一個引數上使用它來由給定引數推斷,它實際上不會從中推斷出來,只會使用默認型別 - 很煩人。
我已經接近解決它了,但我剩下的唯一問題是屬性值的智能感知沒有顯示該屬性的所有可用值,我希望對 TypeScript 有更多了解的人可以幫助我過了這最后一道關卡。
我在這里有一個打字稿操場代碼的鏈接,以便您可以以最簡單的形式對其進行修改。
下面也是代碼:
const EventType = Symbol('eventType');
type Unsubscribe = () => void;
type AnyFunction<ReturnType = any> = (...args: any[]) => ReturnType;
interface SingleResultEventCreateProps {
mode: 'passthrough';
}
interface ArrayResultEventCreateProps {
mode?: 'concurrent' | 'in-turn';
}
type EventCreateProps = SingleResultEventCreateProps | ArrayResultEventCreateProps
type ArrayResultEventDelegate<FuncType extends AnyFunction = AnyFunction> = ((delegate: FuncType) => Unsubscribe) & { [EventType]: 'array'; };
type SingleResultEventDelegate<FuncType extends AnyFunction = AnyFunction> = ((delegate: FuncType) => Unsubscribe) & { [EventType]: 'single'; };
type EventDelegate<FuncType extends AnyFunction = AnyFunction> = ArrayResultEventDelegate<FuncType> | SingleResultEventDelegate<FuncType>;
function create<FuncType extends AnyFunction>(): ArrayResultEventDelegate<FuncType>;
function create<FuncType extends AnyFunction>(props: ArrayResultEventCreateProps): ArrayResultEventDelegate<FuncType>;
function create<FuncType extends AnyFunction>(props: SingleResultEventCreateProps): SingleResultEventDelegate<FuncType>;
function create<FuncType extends AnyFunction>(props: EventCreateProps = {}): EventDelegate<FuncType> {
return null as unknown as EventDelegate<FuncType>;
}
// the below works perfectly...except that the intellisense for mode offers only concurrent or in-turn, it does not offer passthrough as an possible value of mode.
const a = create<()=>string>({ mode: 'passthrough' }); // typeof a === SingleResultEventDelegate <-- correct
const b = create<()=>string>({ mode: 'concurrent' }); // typeof b === ArrayResultEventDelegate <-- correct
const c = create<()=>string>({ mode: 'in-turn' }); // typeof c === ArrayResultEventDelegate <-- correct
/*
to replicate my issue, remove the passthrough text from the mode property above, so it looks like this:
const a = create<()=>string>({ mode: '' });
then make sure your cursor is between the two quotes above and press ctrl space and you'll see it only offers concurrent and in-turn as options.
Is there any way to offer all three modes via intellisense and still get the right return types?
*/
uj5u.com熱心網友回復:
看來您遇到了 TypeScript 的缺失功能,報告于microsoft/TypeScript#44183。TypeScript 似乎只選擇了其中一種多載來顯示潛在的完成。你可以給這個問題一個??,但不清楚何時甚至是否會解決這個問題。
解決此問題的一種可能方法是為您提供一個虛擬多載,該多載具有您想要支持的所有完成,但在您呼叫該函式時永遠不會實際選擇。一種“僅檔案”的多載。它可能看起來像這樣:
// call signature 1
function create<F extends AnyFunction>(
): ArrayResultEventDelegate<F>;
// dummy overload for intellisense only
function create<F extends AnyFunction>(
props: (ArrayResultEventCreateProps | SingleResultEventCreateProps) & { ugh: never }
): ArrayResultEventDelegate<F> | SingleResultEventDelegate<F>;
// call signature 2
function create<F extends AnyFunction>(
props: ArrayResultEventCreateProps
): ArrayResultEventDelegate<F>;
// call signature 3
function create<F extends AnyFunction>(
props: SingleResultEventCreateProps
): SingleResultEventDelegate<F>;
所以我在你遇到問題的兩個之前添加了一個呼叫簽名。它接受兩種輸入道具型別的聯合,因此它會建議兩者。但它也與相交{ugh: never},因此輸入需要具有ughtype 的屬性never。這極不可能發生,所以當你實際呼叫create()它時,永遠不要選擇這個組合多載。
讓我們確保它有效。這些東西仍然按照您的意愿行事:
const a = create<() => string>({ mode: 'passthrough' });
// typeof a === SingleResultEventDelegate <-- correct
const b = create<() => string>({ mode: 'concurrent' });
// typeof b === ArrayResultEventDelegate <-- correct
const c = create<() => string>({ mode: 'in-turn' });
// typeof c === ArrayResultEventDelegate <-- correct
所以沒有選擇虛擬過載。但是這個多載現在向您顯示了可能的字串完成的預期串列:
const d = create<() => string>({mode: ""})
// ^ ?? "concurrent"
// ?? "in-turn"
// ?? "passthrough"
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/480206.html
