首页 > 解决方案 > 联合类型和条件类型的问题

问题描述

我有以下类型声明:

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">;

游乐场链接

标签: typescriptgenericstypescript-genericsunion-typesconditional-types

解决方案


原因boolean和联合具有相似的行为是因为编译器将boolean其视为文字类型的联合truefalse因此type boolean = true | false(尽管此定义不明确存在)

该行为的原因是通过设计条件类型分布在联合上。这是设计的行为,允许实现各种强大的东西。您可以在此处阅读有关该主题的更多信息

如果您不希望条件分布在联合上,您可以在元组中使用该类型(这将阻止该行为)

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">;

推荐阅读