【问题标题】:Define an interface that is a more concrete type in typescript?在打字稿中定义一个更具体类型的接口?
【发布时间】:2021-11-14 11:34:43
【问题描述】:

我在 typescript 中有一个类型,它是一个对象,它的所有属性都应该是 number 类型。基于这种类型,我想创建比原始类型更具体的各种接口,并将它们作为泛型参数传递给一个类,该类除了扩展我的基本类型的泛型,但我总是收到以下打字稿错误:

类型“yyy”中缺少类型“xxx”的索引签名

在打字稿中是否可以做类似于我想做的事情?我能做到的最好的事情是告诉我的moreConcrete 接口,它扩展了basic 类型,这样,错误就消失了,但是在尝试使用该接口时我失去了自动完成和其他智能感知功能。

这里有一个例子:Fiddle

这是小提琴中的代码:

type basic = {
    [key: string]: number
}

class A<TInput extends basic> {

}

interface moreConcrete {
    a: number,
    b: number
}
const test = new A<moreConcrete>(); // this does not work like this

interface otherMoreConcrete extends basic {
    a: number,
    b: number
}
const test2 = new A<otherMoreConcrete>(); // this does not give any errors
const typeTest: keyof otherMoreConcrete = 'as'; // this accepts as as a key of otherMoreConcrete, because of the extension to `basic`, this should be an error

【问题讨论】:

  • @kaya3 在课堂上省略了接口的使用,因为没有它也可以重现问题。我原来的basic 界面在实际代码中也不是那么简单,这只是为了尝试以一种简单的方式显示我遇到的问题。基本上,我需要的是,我可以定义一个限制扩展该类型的接口的类型吗?
  • 你可以限制类的泛型参数,所以如果你传递非数字成员class A&lt;T extends Record&lt;keyof T, number&gt;&gt;typescriptlang.org/play?#code/…的东西会出错

标签: typescript


【解决方案1】:

为了更好的理解这个问题,请看this的回答。

TL;TR

interfaces 默认没有索引,而types 有。 为了摆脱错误,只需使用type 而不是interface。我的意思是,而不是使用:

interface moreConcrete {
    a: number,
    b: number
}

使用

type moreConcrete= {
    a: number,
    b: number
}
const test = new A<moreConcrete>(); // ok

您可以在我的article 中找到更多示例

使用type 代替interface 是否超级安全?我不这么认为。这完全取决于您的代码和您想要实现的目标。我不知道所有的边缘情况。所以,它应该被彻底测试。

在这种特殊情况下,使用type 而不是interface 可能是安全的,因为A 类需要索引类型。

至于第二个问题:

interface otherMoreConcrete extends basic {
    a: number,
    b: number
}

const test2 = new A<otherMoreConcrete>(); // this does not give any errors
const typeTest: keyof otherMoreConcrete = 'as'; // this accepts as as a key of otherMoreConcrete, because of the extension to `basic`, this should be an error

这里没有错误,因为otherMoreConcrete接口和moreConcrete有很大区别。 otherMoreConcrete 扩展 basic。这意味着它具有索引属性。我的意思是除了拥有ab 之外,它还接受任何字符串键。


type otherMoreConcrete = {
    [x: string]: string;
    a: "a";
    b: "b";
}

因此,如果您想在最后一个示例中触发 en 错误,只需使用 type 而不是 interface

type basic = {
    [key: string]: number
}

class A<TInput extends basic> {}


type moreConcrete = {
    a: number,
    b: number
}
const test = new A<moreConcrete>(); // ok

type otherMoreConcrete = {
    a: number,
    b: number
}


const test2 = new A<otherMoreConcrete>(); // ok
const typeTest: keyof otherMoreConcrete = 'as'; // error

Playground

【讨论】:

    猜你喜欢
    • 2016-08-29
    • 1970-01-01
    • 2018-02-22
    • 2023-02-07
    • 2018-08-11
    • 1970-01-01
    • 2017-09-26
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多