编译器没有说明类型上不存在的属性

时间:2016-07-27 13:16:42

标签: typescript ecmascript-6

此接口描述了应该只包含方法的对象,这些方法将返回具有一些required属性的对象。

编译时出现的预期恐慌:

  • 添加属性而不是方法// ok
  • 更改所需的属性值类型// ok
  • 删除所需的属性// ok
  • 添加新属性//沉默

样品

type Obj = {
  required: string;
}
interface ObjWithMethods {
  [req: string]: () => Obj;
}

let some: ObjWithMethods = {
  meth1: () => ({
    required: "",
    PROPERTY_WICH_NOT_EXIST_ON_TYPE: 1, // no panic from compiler
  }),
  meth2: () => ({
    required: "",
  })
}

如何让编译器在类型上不存在的属性上尖叫?

1 个答案:

答案 0 :(得分:1)

为什么编译器没有抱怨这个额外的属性?

interface A {
    str: string;
    num: number;
}

let a1 = { str: "string", num: 0 }; // type of a1: { str: string, num: number }
let a2 = { str: "string", num: 0 } as A; // type of a2: A
let a3: A = { str: "string", num: 0 }; // type of a3: A

let a4 = { str: "string", num: 0, bool: true }; // type of a4: { str: string, num: number, bool: boolean }
let a5 = { str: "string", num: 0, bool: true } as A; // type of a5: A
console.log(a5.bool); // error
let a6: A = { str: "string", num: 0, bool: true }; // error

code in playground

正如您所看到的,前三个(a1,a2和a3)没有任何问题,因为它们都包含strnuma6的错误正如您所期望的那样,编译器并不喜欢声明为A的内容包含未声明的属性界面。
但是,a5完全没问题,因为它可以从A的对象投射到A,但也有更多数据。
这当然没问题,因为一旦你把它归结为A,你就无法再访问那个额外的属性了,这就是a5.bool引发错误的原因。

您的代码中发生的事情正是a5所发生的事情,编译器强制转换:

{
    required: "",
    PROPERTY_WICH_NOT_EXIST_ON_TYPE: 1
}

Obj,并且没有冲突,就像a5投放到A时没有冲突一样,所以:

let myObj = some["meth1"]();

myObj类型Obj,所以这个:

console.log(myObj.PROPERTY_WICH_NOT_EXIST_ON_TYPE);

导致错误,即使实际上(并且在运行时)myObj.PROPERTY_WICH_NOT_EXIST_ON_TYPE确实存在。

如果您希望编译器抱怨它,那么您可以执行以下操作:

function createMethod(value: Obj): () => Obj {
    return () => value;
}

let some: ObjWithMethods = {
    meth1: createMethod({
        required: "",
        PROPERTY_WICH_NOT_EXIST_ON_TYPE: 1 // error here
    })
}

code in playground