我最近偶然发现了TypeScript中这种奇怪的(imo)行为。 在编译期间,只有当接口没有必填字段时,如果预期变量的类型是接口,它才会抱怨多余的属性。链接到TypeScript Playground#1:http://goo.gl/rnsLjd
interface IAnimal {
name?: string;
}
class Animal implements IAnimal {
}
var x : IAnimal = { bar: true }; // Object literal may only specify known properties, and 'bar' does not exist in type 'IAnimal'
var y : Animal = { bar: true }; // Just fine.. why?
function foo<T>(t: T) {
}
foo<IAnimal>({ bar: true }); // Object literal may only specify known properties, and 'bar' does not exist in type 'IAnimal'
foo<Animal>({ bar: true }); // Just fine.. why?
现在,如果你添加一个强制性的&#39; IAnimal接口的字段并在Animal类中实现它将开始抱怨&#39; bar&#39;是机器人接口和类的多余属性。链接到TypeScript Playground#2:http://goo.gl/9wEKvp
interface IAnimal {
name?: string;
mandatory: number;
}
class Animal implements IAnimal {
mandatory: number;
}
var x : IAnimal = { mandatory: 0, bar: true }; // Object literal may only specify known properties, and 'bar' does not exist in type 'IAnimal'
var y : Animal = { mandatory: 0, bar: true }; // Not fine anymore.. why? Object literal may only specify known properties, and 'bar' does not exist in type 'Animal'
function foo<T>(t: T) {
}
foo<IAnimal>({ mandatory: 0, bar: true }); // Object literal may only specify known properties, and 'bar' does not exist in type 'IAnimal'
foo<Animal>({ mandatory: 0,bar: true }); // Not fine anymore.. why? Object literal may only specify known properties, and 'bar' does not exist in type 'Animal'
如果有人对于为什么会这样有效,请做一些见解 我很好奇为什么会这样。
答案 0 :(得分:3)
来自pull request的以下三个要点阐明了在操场上使用的TS 1.6中新的严格行为:
- 每个对象文字最初都被视为&#34;新鲜&#34;。
- 当一个新的对象文字分配给一个变量或为一个非空目标类型的参数 [强调添加]传递时,对象文字指定的属性是错误的#39; t存在于目标类型中。
- 新鲜度在类型断言中消失,或者当对象文字的类型变宽时消失。
我在源代码function hasExcessProperties
和function isKnownProperty
中找到了评论:
// Check if a property with the given name is known anywhere in the given type. In an object type, a property // is considered known if the object type is empty and the check is for assignability, if the object type has // index signatures, or if the property is actually declared in the object type. In a union or intersection // type, a property is considered known if it is known in any constituent type. function isKnownProperty(type: Type, name: string): boolean { if (type.flags & TypeFlags.ObjectType) { const resolved = resolveStructuredTypeMembers(type); if (relation === assignableRelation && (type === globalObjectType || resolved.properties.length === 0) || resolved.stringIndexType || resolved.numberIndexType || getPropertyOfType(type, name)) { return true; } } else if (type.flags & TypeFlags.UnionOrIntersection) { for (const t of (<UnionOrIntersectionType>type).types) { if (isKnownProperty(t, name)) { return true; } } } return false; }
因此,第一个示例中的目标类型Animal
(类)是一个空类型 - 它没有属性,因为您没有在类中实现name
属性(因此resolved.properties.length === 0
是在isKnownProperty
函数中为true。另一方面,IAnimal
已定义属性。
我可能在技术上有点描述了这种行为但是...希望,我明确表示并且希望,我没有在路上犯错误。