为什么Readonly<T>可以赋值给T,但ReadonlyArray<T>却不能赋值给Array<T>?

5
type Foo = {a: number}
let obj: Foo = {} as Readonly<Foo>
let arr: number[] = [] as ReadonlyArray<number>

我了解ReadonlyArray类型会移除任何可变的Array方法,这意味着只读数组不符合预期的数组接口。
但我不明白为什么只读对象被认为是安全的传递到一个期望可变对象的函数中。在技术上,只读对象缺少一个隐式的setter方法,所以它实际上并没有遵循预期的可变接口。 Playground链接

1
我写了一个 ESLint 插件,可能会有所帮助:https://github.com/danielnixon/eslint-plugin-total-functions#total-functionsno-unsafe-assignment - danielnixon
1个回答

3

ReadonlyArray 实际上是另一种类型,因此ArrayReadonlyArray 在结构上是不同的。正如您注意到的,ReadonlyArray 的实例缺少一些方法,比如pushpop

但是对于对象来说,并非如此。没有单独的ReadonlyObjectReadonlyObjectConstructor。许多不应被允许的操作都是被允许的:

type Foo = {a: number}

let mutable: Foo = { a: 0 };
let immutable: Readonly<Foo> = { a: 0 };

/**
 * Both work without error.
 */
mutable = immutable;
immutable = mutable;

/**
 * These two work as well.
 */
Object.assign(immutable, { foo: 1 });
Object.defineProperty(immutable, 'bar', {
    value: 2
});

TypeScript使用结构类型系统。两个形状完全相同的对象可以互相赋值。然而,readonly修饰符不影响结构,只影响行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接