联合类型和条件类型的问题
Issue with union types and conditional types
我有以下类型声明:
class MyGeneric<T> { }
type ReplaceType<T> = T extends Function ? T : MyGeneric<T> | T;
ReplaceType<T>
应解析为 MyGeneric<T> | T
或 T
,具体取决于 T
是否为函数:
// Input type: string
// Expected type: string | MyGeneric<string>
// Actual type: string | MyGeneric<string>
type Test1 = ReplaceType<string>;
// Input type: () => void
// Expected type: () => void
// Actual type: () => void
type Test2 = ReplaceType<() => void>;
不幸的是,这不适用于 boolean
和联合类型:
// Input type: boolean
// Expected type: boolean | MyGeneric<boolean>
// Actual type: boolean | MyGeneric<true> | MyGeneric<false>
type Test3 = ReplaceType<boolean>;
// Input type: "foo" | "bar"
// Expected type: "foo" | "bar" | MyGeneric<"foo" | "bar">
// Actual type: "foo" | "bar" | MyGeneric<"foo"> | MyGeneric<"bar">
type Test4 = ReplaceType<"foo" | "bar">;
boolean
和联合具有相似行为的原因是因为编译器将 boolean
视为文字类型 true
和 false
的联合,所以 type boolean = true | false
(虽然这个定义并不明确存在)
该行为的原因是设计条件类型分布在联合上。这是设计的行为,可以实现各种强大的功能。您可以阅读有关该主题的更多信息 here
如果您不希望条件分配给联合,您可以在元组中使用类型(这将防止这种行为)
class MyGeneric<T> { }
type ReplaceType<T> = [T] extends [Function] ? T : MyGeneric<T> | T;
// Input type: string
// Expected type: string | MyGeneric<string>
// Actual type: string | MyGeneric<string>
type Test1 = ReplaceType<string>;
// Input type: () => void
// Expected type: () => void
// Actual type: () => void
type Test2 = ReplaceType<() => void>;
// Input type: boolean
// Expected type: boolean | MyGeneric<boolean>
// Actual type: boolean | MyGeneric<boolean>
type Test3 = ReplaceType<boolean>;
// Input type: "foo" | "bar"
// Expected type: "foo" | "bar" | MyGeneric<"foo" | "bar">
// Actual type: "foo" | "bar" | MyGeneric<"foo" | "bar">
type Test4 = ReplaceType<"foo" | "bar">;
我有以下类型声明:
class MyGeneric<T> { }
type ReplaceType<T> = T extends Function ? T : MyGeneric<T> | T;
ReplaceType<T>
应解析为 MyGeneric<T> | T
或 T
,具体取决于 T
是否为函数:
// Input type: string
// Expected type: string | MyGeneric<string>
// Actual type: string | MyGeneric<string>
type Test1 = ReplaceType<string>;
// Input type: () => void
// Expected type: () => void
// Actual type: () => void
type Test2 = ReplaceType<() => void>;
不幸的是,这不适用于 boolean
和联合类型:
// Input type: boolean
// Expected type: boolean | MyGeneric<boolean>
// Actual type: boolean | MyGeneric<true> | MyGeneric<false>
type Test3 = ReplaceType<boolean>;
// Input type: "foo" | "bar"
// Expected type: "foo" | "bar" | MyGeneric<"foo" | "bar">
// Actual type: "foo" | "bar" | MyGeneric<"foo"> | MyGeneric<"bar">
type Test4 = ReplaceType<"foo" | "bar">;
boolean
和联合具有相似行为的原因是因为编译器将 boolean
视为文字类型 true
和 false
的联合,所以 type boolean = true | false
(虽然这个定义并不明确存在)
该行为的原因是设计条件类型分布在联合上。这是设计的行为,可以实现各种强大的功能。您可以阅读有关该主题的更多信息 here
如果您不希望条件分配给联合,您可以在元组中使用类型(这将防止这种行为)
class MyGeneric<T> { }
type ReplaceType<T> = [T] extends [Function] ? T : MyGeneric<T> | T;
// Input type: string
// Expected type: string | MyGeneric<string>
// Actual type: string | MyGeneric<string>
type Test1 = ReplaceType<string>;
// Input type: () => void
// Expected type: () => void
// Actual type: () => void
type Test2 = ReplaceType<() => void>;
// Input type: boolean
// Expected type: boolean | MyGeneric<boolean>
// Actual type: boolean | MyGeneric<boolean>
type Test3 = ReplaceType<boolean>;
// Input type: "foo" | "bar"
// Expected type: "foo" | "bar" | MyGeneric<"foo" | "bar">
// Actual type: "foo" | "bar" | MyGeneric<"foo" | "bar">
type Test4 = ReplaceType<"foo" | "bar">;