【问题标题】:Interface cannot extend mapped type in conditional type接口不能在条件类型中扩展映射类型
【发布时间】:2021-04-10 01:18:00
【问题描述】:

在调试我的程序时,我注意到以下示例产生了编译错误 (playground)。

type Foo = {key: string};
interface Bar {key: string};

type Baz = Foo extends Record<string, unknown>? any: never;
type Qux = Bar extends Record<string, unknown>? any: never;

const baz: Baz = 0;
const qux: Qux = 0; // Type 'number' is not assignable to type 'never'.

似乎接口不能扩展 Record&lt;string, unknown&gt; 而类型可以。我知道 TypeScript 中的类型和接口之间存在一些差异,我怀疑映射类型不能在接口中使用这一事实可能会解释这种行为。我无法完全理解为什么这种地图类型限制会导致 Qux 成为 never,即使是这样。

此外,interface Foobar extends Record&lt;string, unknown&gt; { key: string }; 是一个有效的接口定义,这让我更加困惑。

谁能帮我理解这个错误?

【问题讨论】:

标签: typescript interface conditional-types mapped-types


【解决方案1】:

这是因为类型别名具有隐式索引签名,但接口没有。

如果您将索引签名添加到接口 - Qux 将导致 any

interface Bar { 
    key: string;
    [p: string]: string;
};

Playground

更多信息here:

此行为目前是设计使然。因为接口可以通过额外的声明来扩充,但类型别名不能,所以推断类型别名的隐式索引签名比接口的隐式索引签名“更安全”(在那个上加了重引号)。

【讨论】:

  • 此技术可用于检查类型是否为接口。但不确定它是否有用)))
  • 我实际上检查了引用的问题,但不知道它是否相关,谢谢。不过,我的问题仍然存在;为什么interface Foobar extends Record&lt;string, unknown&gt; { key: string }; 有效?如果表达式中的{ key: string } 是一个接口(不是类型别名),它没有索引签名并且不能是Record&lt;string, unknown&gt; 的部分类型,可以吗?我可能遗漏了一些基本的东西......
  • @yudai-nkt 您正在将“接口扩展”typescriptlang.org/docs/handbook/… 与条件类型typescriptlang.org/docs/handbook/… 混合使用
  • 啊,明白了。是的,我想太多了,不知怎么混淆了这两个extends。再次感谢!
猜你喜欢
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2019-04-07
  • 2022-01-22
  • 2019-03-21
  • 2021-08-07
相关资源
最近更新 更多