为什么在这种情况下,TypeScript类型推断会失败?

3

我想了解为什么类型S1never,但是当我删除labelcustomRef属性时,我得到了正确的string结果。当我删除valuelabel属性时,我会得到一个unknown结果。

export interface BaseInputProps<TStored> {
  value: TStored;
  customRef?: (selfProps: this) => void;
}

export interface TestInput extends BaseInputProps<string> {
  label: string;
}

type InferStoredType<T> = T extends BaseInputProps<infer TT> ? TT : never;

type S1 = InferStoredType<TestInput>;

这里发生了什么?
Typescript版本为3.7.5。在Typescript playground上的工作方式相同。
1个回答

2
这与结构差异和弱类型weak type有关。因此,让我们在所有情况下了解您的问题。
情况1:默认情况下,它从来不是。
当您尝试使用interface BaseInputProps<string>扩展interface TestInput时,它将尝试检查所有属性的类型是否兼容,但在这种情况下,customRef?:(selfProps:this)=> void; 类型(selfProps:this)=> void无法分配给string,反之亦然。这就是为什么它是虚假继承,导致S1是never
情况2:当您删除标签和customRef时,它是字符串。
当你删除标签和customRef时,因为只剩下一个必需属性value,所以interface BaseInputProps和interface TestInput将会被正确推断类型。但是,当你删除value和label时,它们变成了可选属性,TypeScript无法保证这种情况下的类型推断。至于为什么故意进行这种更改,这是一个问题。但是,考虑到规范更改的范围,很难看到这种更改。请阅读弱类型条件类型以获取更多信息。

我还是不明白为什么第一个情况下是“never”? - Hristo Kolev
@HristoKolev 更新了第一个默认情况的答案。 - cauchy
"type (selfProps: this)=> void" 与 "string" 之间不可互相赋值。但是为什么要检查这个呢?它们有不同的名称,这些属性彼此之间没有任何关联。 - Hristo Kolev
接口的结构必须完全相同,才能使 T extends BaseInputProps<infer TT> 成立。 - cauchy
我理解为“如果T实现了BaseInputProps的某些内容,给我这个东西”。这正确吗? - Hristo Kolev
并不是我所指的,因为BaseInputProps具有可选属性,所以T也需要具有可选属性。否则,两者在结构上是不同的。 - cauchy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接