使用接口在typescript中键入匿名对象

Saf*_*ari 10 strong-typing typescript

我有一个接口IBase和一个包含一些其他对象的变量(在示例中我刚添加了基础以便更好地演示)

interface IBase {
    height?:number;
    width?:number;
}

var element = {
    base: {

    }
}
Run Code Online (Sandbox Code Playgroud)

我怎么能说可变元素.base所拥有的对象来自IBase类型?我知道我可以为包含base等类型的元素变量创建一个类型,但是也可以在不这样做的情况下键入该场景.

bas*_*rat 19

Van den Brink的答案很好.就像演示另一种选择:

var element = {
    base: <IBase> {

    }
}
Run Code Online (Sandbox Code Playgroud)

这也将提供所需的智能感知:

在此输入图像描述

  • 在这里使用类型断言只能给您带来部分好处,因为它可以使您强制转换为对象文字实际不符合规范的类型。也就是说,它使您具备了智能感知能力,但没有使您获得良好的静态类型检查。AFAICT进行静态类型检查的唯一方法是将文字分配给没有类型声明的正确类型的变量。Dick van den Brink对IMO有更好的回答。 (2认同)

Pau*_*ood 8

@basarat 的优秀回答现在需要一些更新;现在使用尖括号会产生tslint错误:

[tslint] 禁止使用“<>”语法进行类型断言。请改用“as”语法。(无角括号类型断言)

解决方法很简单:

const element = {
    base: {} as IBase
}
Run Code Online (Sandbox Code Playgroud)

这也提供了您想要的智能感知(自动完成)。


Dic*_*ink 5

如果将var元素的声明更改为以下内容,它将知道基数:

var element: { base: IBase; } = {
    base: {
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您还可以像这样为它创建一个新接口,从而使它更具可重用性:interface IElement {base:IBase; },然后像下面这样使用它:var element:IElement = {base:{}}


Fen*_*ton 5

您不小心导致自己的界面声明出现问题.这是一个微妙的结构类型语言.

interface IBase {
    height?:number;
    width?:number;
}
Run Code Online (Sandbox Code Playgroud)

因为所有属性都是可选的,所以界面本质上是{}.即任何对象都满足此接口.在大多数情况下,这种做法太普遍了.

例如,这样做是完全可以接受的:

var x: IBase = {
    a: 'efsdsdf',
    v: 'sdfdsf' 
};
Run Code Online (Sandbox Code Playgroud)

我想你会同意,确实这个对象是没有用的任何地方我想用一个IBase对象.

有了这个,您可能会发现最优雅的解决方案是创建一个与您的element定义相匹配的界面.

interface IElement {
    base: {
        height?:number;
        width?:number;
    }
}

var element: IElement = {
    base: {
        height: 4
    }
}
Run Code Online (Sandbox Code Playgroud)