【问题标题】:Generic conditional type resolves to never when the generic type is set to never当泛型类型设置为从不时,泛型条件类型解析为从不
【发布时间】:2019-11-21 23:11:51
【问题描述】:

当(此属性的)泛型参数为never 时,我需要一个从指定类型中排除泛型属性的泛型类型。为此,我使用了Omit 和条件类型。例如,当泛型参数设置为 number 时,它的行为与预期一样,但当泛型类型设置为 never 时,类型解析为 never 而不是排除指定的属性 (Playground):

type BaseType<T> = {
  prop1: string;
  genProp1: T;
};

type Excluded<T> = T extends never ? Omit<BaseType<T>, "genProp1"> : BaseType<T>;

const obj1: Excluded<number> = {
  genProp1: 5,
  prop1: "something, something"
};

//obj2 is never
const obj2: Excluded<never> = {
  prop1: "dark side" //error: Type 'string' is not assignable to type 'never'
};

为什么要这样做,我怎样才能让它返回正确的类型 ({ prop1: string })?

编辑: 比较 null 而不是 never 解决了这个问题。当我使用never 时,我仍然想知道发生了什么。

【问题讨论】:

    标签: typescript generics conditional-types


    【解决方案1】:

    Conditional types distribute over naked type parameters。这意味着条件类型将应用于联合的每个成员。 never 被视为空联合。所以条件类型永远不会被应用(因为联合中没有成员可以应用它)导致 never 类型。

    简单的解决方案是使用元组禁用条件类型的分配行为:

    type BaseType<T> = {
        prop1: string;
        genProp1: T;
    };
    
    type Excluded<T> =
        [T] extends [never] ? Omit<BaseType<T>, "genProp1"> : BaseType<T>;
    
    const obj1: Excluded<number> = {
        genProp1: 5,
        prop1: "bla"
    };
    
    const obj2: Excluded<never> = {
        prop1: "dwdadw"
    };
    
    

    Playground Link

    【讨论】:

    • 好的,现在说得通了。您对使用您的解决方案和使用 null 而不是 never 之间的性能或“微妙问题”有什么想法(请参阅我上面的编辑)?
    • @AndreiV 取决于您希望T 包含null 时的行为。带有null 的版本将从genProp1 中删除nulltypescriptlang.org/play/index.html#code/…
    • 嗯,我明白了...在我的特殊情况下,这不是问题,因为属性将被完全排除或设置为(很可能)string
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2013-06-14
    • 2012-08-11
    • 2021-12-01
    • 1970-01-01
    相关资源
    最近更新 更多