条件类型中类型和接口有什么区别?

问题描述 投票:0回答:2
type Handlers = {
    [name: string | number]: () => void
}

type H1 = { 
    "click": () => void 
}

interface H2 {
    "click": () => void
}

type A = H1 extends Handlers ? 'yes' : 'no' // yes
type B = H2 extends Handlers ? 'yes' : 'no' // no

TSC v5.1.6.

虽然H1和H2具有相同的结构,但我得到A是“是”而B是“否”。

extends 子句中的类型和接口似乎有些区别。 typescript手册我看了两遍,没找到相关解释。

不知道是否和TSC的一些底层逻辑有关?

Interface的类型检查比Type更严格吗?

typescript types interface conditional-types
2个回答
0
投票

type 可以表示很多种类型,包括原始类型、并集、交集等

接口更注重对象形状定义,可以通过其他接口进行扩展。

type 在条件类型中按预期工作,条件类型检查指定类型是否可分配给另一个类型。

条件类型中的接口表现不同。 TypeScript 的条件类型使用结构兼容性进行检查,并且接口是开放式的。

H1 扩展了 Handlers,因为它与结构完全匹配,因此输入 A = 'yes'。 由于类型和接口之间的行为差异,H2 不会在条件类型上下文中扩展处理程序,因此输入 B = 'no'。

示例:-

类型:-

type H1 = { 
    "click": () => void 
}
type A = H1 extends Handlers ? 'yes' : 'no' // yes

接口:-

interface H2 {
    "click": () => void
}
type B = H2 extends Handlers ? 'yes' : 'no' // no

interface H2Extended extends H2 {
    "hover": () => void
}

let h2Var: H2;
let h2ExtVar: H2Extended;

h2Var = h2ExtVar; // This is valid

0
投票

在 TypeScript 中,

type
interface
都可以定义对象形状,但它们有一些细微的区别。在您的示例中,问题的出现是因为它们如何与
extends
子句交互。

当您将

type
extends
一起使用时,TypeScript 会检查正在检查的类型(左侧)是否符合与其比较的类型(右侧)的约束。在你的例子中,H1扩展了
Handlers
,因为
Handlers
允许任何字符串或数字作为键,并且H1有一个匹配的属性
"click"

但是,对于像

interface
这样的
H2
,即使它与
H1
具有相同的结构,TypeScript 也不会将其视为扩展
Handlers
。这种行为源于内部 TypeScript 规则,这些规则使得两者在某些情况下的行为略有不同。

简单来说,

type
interface
都定义了对象形状,但是在处理
extends
和映射类型时,它们的行为可能会因 TypeScript 内部评估它们的方式而有所不同。根据您的代码需求选择正确的方法非常重要。

© www.soinside.com 2019 - 2024. All rights reserved.