簡體   English   中英

TypeScript如何處理接口和類中的多余屬性的區別

[英]Difference in how TypeScript handles excess properties in interfaces and classes

我最近偶然發現了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?

現在,如果你向IAnimal接口添加一個'強制'字段並在Animal類中實現它,它將開始抱怨'bar'是bot接口和類的多余屬性。 鏈接到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'

如果有人有一些見解,為什么它的工作原理,請做。
我很好奇為什么會這樣。

來自pull請求的以下三個要點揭示了在操場上使用的TS 1.6中的新嚴格行為:

  • 每個對象文字最初都被認為是“新鮮的”。
  • 將新對象文字分配給變量或為非空目標類型的參數傳遞[強調添加]時,對象文字指定目標類型中不存在的屬性是錯誤的。
  • 新鮮度在類型斷言中消失,或者當對象文字的類型變寬時消失。

我在源代碼function hasExcessProperties找到了function hasExcessPropertiesfunction 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屬性(因此在isKnownProperty函數中resolved.properties.length === 0為true)。 另一方面, IAnimal具有定義的屬性。

我可能已經在技術上描述了這種行為,但是...希望,我明確表示並希望,我沒有在路上犯錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM