这是 TypeScript 错误吗?

互联网 行业动态 更新时间:2024-06-13 00:19:32

jca*_*alz 7

这是 TypeScript 中的预期行为。

TypeScript 的类型系统在很大程度上是结构性的,而不是名义上的。所以重要的是类型的形状结构,而不是它的名称声明。因此,TypeScript 编译器可以确定 typeA是(或“可分配给”或“扩展”)的子类型,无论您是否在. 仅当 的表观性质在 中具有兼容性质时才重要:BABA BABBA

interface A {
    x: string;
    y: number;
}

interface B {
    x: string;
}

const a: A = { x: "", y: 0 };
const b: B = a; // okay, A extends B

最后一行不像名义上键入的语言那样是错误的。


请注意,“表观属性”意味着即使是像,和等一些原语也可以被认为在结构上与对象类型兼容,因为当您对它们进行索引时,JavaScript 会自动将一些原语包装在包装器对象中。所以类型是 的子类型:numberstringboolean{length: number}string

interface L { length: number };
const l: L = "hello"; // okay

因为string值具有 type 的明显length属性number


在 TypeScript 中,class声明也通常在结构上进行处理(尽管在某些情况下会发生类似名义类型的类型,例如usinginstanceof来区分两个类或添加privateorprotected成员时)。因此,如果您有一个空类:

class GroupLeader { }

此类在结构上与空对象类型相同,空对象类型{}是没有成员的对象类型。因此,任何可以像对象一样被索引的值都将被视为可分配给该类:

function foo(leader: GroupLeader): void { /* snip: do stuff */ }

foo(true); // okay
foo(123); // okay
foo({}); // okay
foo(() => 3); // okay
foo(new Date()); // okay
foo(Symbol("oops")); // okay

foo(null); // error
foo(undefined); // error

只有null并且undefined不可分配给GroupLeader, 因为如果您像对象一样对它们进行索引,则会引发运行时错误nullundefined


这就是它发生的原因。通常,您希望防止此类行为,因此最好避免使用空类和空对象类型,即使在示例代码中也是如此。(有些过时的)TypeScript FAQ有很多关于这个的条目,比如为什么所有类型都可以分配给空接口?为什么这些空类表现得很奇怪?. 如果您希望编译器将两种类型视为不同的类型,则应确保它们具有不兼容的形状。

添加任何boolean不共享的属性GroupLeader都会改变事情:

class GroupLeader { unsnip = 0 };

function foo(leader: GroupLeader): void { /* snip: do stuff */ }
foo(true); // error
foo(123); // error
foo({}); // error
foo(() => 3); // error
foo(new Date()); // error
foo(Symbol("oops")); // error

foo(new GroupLeader()); // okay

当然,仍然有可能传入一些结构上兼容的东西:

foo({ unsnip: 123 }); // okay

如果需要,您可以尝试阻止这种情况(private属性会这样做),但阻力最小的路径是只编写只关心结构兼容性的代码。无论foo()实现是什么,它都应该只关心的结构leader不是声明

Playground 代码链接

更多推荐

这是,错误,TypeScript

本文发布于:2023-04-21 10:01:28,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:这是   错误   TypeScript

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!