我正在嘗試撰寫一個使用泛型和條件型別回傳值的函式,如下所示:
interface Foo<T> {
bar: T extends true ? string : undefined;
id: string;
}
interface Options<T> {
withBar?: T;
}
function createFoo<T extends boolean>({ withBar }: Options<T>): Foo<T> {
return {
id: 'foo',
...(withBar && { bar: 'baz' }),
};
}
以上拋出以下型別錯誤:
Type '{ bar?: "baz" | undefined; id: string; }' is not assignable to type 'Foo<T>'.
Types of property 'bar' are incompatible.
Type '"baz" | undefined' is not assignable to type 'T extends true ? string : undefined'.
Type 'undefined' is not assignable to type 'T extends true ? string : undefined'.
有人能幫我理解為什么會這樣嗎?我指定型別可以是未定義的,所以應該允許它是未定義的。
另外,我想在不實際呼叫它的情況下獲取給定某些引數的函式的回傳型別。那可能嗎?
例如ReturnType<typeof createFoo>不會給我正確的用法型別,createFoo({ withBar: true })因為它還不知道用法。
現場示例在這里
uj5u.com熱心網友回復:
這是一個常見問題,泛型型別在函式實作中沒有解決。您可以撰寫一個函式多載來使您的實作作業:
interface Foo<T> {
bar: T extends true ? string : undefined;
id: string;
}
interface Options<T> {
withBar?: T;
}
function createFoo<T extends boolean>({ withBar }: Options<T>): Foo<T>
function createFoo({ withBar }: Options<boolean>): Foo<true> | Foo<false> {
// The implementation works because the return type is allowed to be Foo<true> or Foo<false>
return {
id: 'foo',
...(withBar && { bar: 'baz' }),
};
}
// The first function overload is taken because it's the first one to match
// the call parameters
const foo = createFoo({ withBar: false }); // foo is of type Foo<false>
打字稿游樂場
uj5u.com熱心網友回復:
必需屬性與可以保存值 or undefined(鍵始終存在)和可選屬性(鍵可能根本不在物件中)之間存在重要區別。看exactOptionalPropertyTypes
在您的文章,您鍵入bar的Foo一如既往的存在,用的條件值string或undefined,但你回傳一個物件,它是有條件有bar在所有關鍵。
在下面的修改中,我重新Foo鍵入以反映bar基于相同布爾條件的可選屬性型別。
我還用Object.assign(編譯器滿意)替換了擴展運算子語法,但是,我不確定為什么這會有所不同。
另外,值得注意的是:如果您嘗試將非物件型別傳播到物件中(例如undefined在您的帖子中),TS 會抱怨:
const obj = {...undefined};
/* ^^^^^^^^^^^^
Error: Spread types may only be created from object types.(2698) */
TS游樂場
type StringId = { id: string };
type Foo<T> = T extends true ? StringId & { bar: string } : StringId;
interface Options<T> {
withBar?: T;
}
function createFoo<T>({ withBar }: Options<T>): Foo<T> {
return Object.assign({id: 'foo'}, (withBar && { bar: 'baz' }));
}
console.log(createFoo({withBar: true})); // { id: "foo", bar: "baz" }
console.log(createFoo({withBar: false})); // { id: "foo" }
console.log(createFoo({})); // { id: "foo" }
另外,我想在不實際呼叫它的情況下獲取給定某些引數的函式的回傳型別。那可能嗎?
是的,通過向函式添加條件回傳型別,這取決于引數:
TS游樂場
function createFoo<T extends boolean>({ withBar }: Options<T>): T extends true ? Foo<true> : Foo<false> {
return Object.assign({id: 'foo'}, (withBar && { bar: 'baz' }));
}
const foo1 = createFoo({withBar: true}); // StringId & { bar: string }
const foo2 = createFoo({withBar: false}); // StringId
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/383520.html
標籤:打字稿
上一篇:如何取消訂閱此訂閱?
