我試圖找到一種方法來從函式多載中獲得嚴格的引數區分。顯然我對這個實作的問題是我的泛型型別T可以擴展到任何繼承AorB道具的東西,所以我在這里得到的錯誤是完全可以預料的('{ type: "A"; a: any; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'AorB'.)。
我正在尋找的是一種方法,<T implements AorB>以便當引數type等于時"A",customProps引數被區分為A道具。
我還試圖避免any在函式實作引數或as回傳中使用。
type A = {
a: string
type: 'A'
}
type B = {
b: string
type: 'B'
}
type AorB = A | B
function createAorB(type: A['type'], customProps?: Partial<Omit<A, 'type'>>): A
function createAorB(type: B['type'], customProps?: Partial<Omit<B, 'type'>>): B
function createAorB<T extends AorB>(type: T['type'], customProps: Partial<Omit<T, 'type'>> = {}): T {
if (type === 'A') {
return {
type,
a: customProps.a || '',
}
}
return {
type,
b: customProps.b || '',
}
}
const newA = createAorB('A')
const newB = createAorB('B')
更新
如果我強制AorB作為回傳值:
function createAorB<T extends AorB>(type: T['type'], customProps: Partial<Omit<T, 'type'>> = {}): AorB
我得到了兩個錯誤Property 'a' does not exist on type 'Partial<Omit<T, "type">>'.以及Property 'b' does not exist on type 'Partial<Omit<T, "type">>'.相應的customProps.a和customProps.b行。
uj5u.com熱心網友回復:
引數串列元組型別形成createAOrB()了一個可區分的聯合,其中第一個元組元素是判別式。它看起來像這樣:
type Args =
[type: "A", customProps?: Partial<Omit<A, "type">>] |
[type: "B", customProps?: Partial<Omit<B, "type">>];
如果你使用rest引數和解構賦值將元素賦值給名為typeand的變數customProps,你可以將rest引數注解為Args,然后編譯器會在你檢查的時候使用控制流分析來縮小customPropstype:
function createAorB(type: A['type'], customProps?: Partial<Omit<A, 'type'>>): A
function createAorB(type: B['type'], customProps?: Partial<Omit<B, 'type'>>): B
function createAorB(...[type, customProps]: Args) {
if (type === 'A') {
return {
type,
a: customProps?.a || '', // okay
}
}
return {
type,
b: customProps?.b || '', // okay
}
}
如果你碰巧有很多型別,AorB而不僅僅是,擴展定義A | B可能會很乏味。Args在這種情況下,您可以讓編譯器為您計算它作為 的函式AorB,如下所示:
type Args = AorB extends infer T ? T extends AorB ? (
[type: T['type'], customProps?: Partial<Omit<T, 'type'>>]
) : never : never;
這使用條件型別推斷復制AorB到一個新的泛型型別引數T中,然后使用它來創建一個分布式條件型別,以便如果是聯合型別(它將操作分布在聯合中),則[type: T['type'], customProps?: Partial<Omit<T, 'type'>>]自動成為聯合型別。TT
您可以驗證它的評估結果是否與上面手動定義的版本相同。
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/495749.html
上一篇:C#:如何多載一個方法以接受多種型別但盡可能少地復制代碼?
下一篇:深層嵌套型別
