gpt4 book ai didi

javascript - TypeScript 处理接口(interface)和类中多余属性的方式不同

转载 作者:数据小太阳 更新时间:2023-10-29 05:29:20 25 4
gpt4 key购买 nike

我最近在 TypeScript 中偶然发现了这种奇怪的 (imo) 行为。在编译期间,只有当预期变量的类型是接口(interface)且接口(interface)没有必填字段时,它才会提示过多的属性。链接到 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 接口(interface)添加一个“强制”字段并在 Animal 类中实现它,它将开始提示“bar”是机器人接口(interface)和类的多余属性。链接到 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 request阐明了在 playground 中使用的 TS 1.6 中新的严格行为:

  • Every object literal is initially considered "fresh".
  • When a fresh object literal is assigned to a variable or passed for a parameter of a non-empty target type [emphasis added], it is an error for the object literal to specify properties that don't exist in the target type.
  • Freshness disappears in a type assertion or when the type of an object literal is widened.

我在源码里找到了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 属性(因此resolved.properties.length === 0isKnownProperty 函数中为真)。另一方面,IAnimal 定义了属性。

我可能已经从技术上描述了这种行为,但是......希望我说清楚了,希望我在整个过程中没有犯错。

关于javascript - TypeScript 处理接口(interface)和类中多余属性的方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33614328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com