本文介绍了DeepReadonly 对象打字稿的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以像这样创建 DeepReadonly 类型:

It is possible to create a DeepReadonly type like this:

type DeepReadonly<T> = {
  readonly [P in keyof T]: DeepReadonly<T[P]>;
};

interface A {
  B: { C: number; };
  D: { E: number; }[];
}

const myDeepReadonlyObject: DeepReadonly<A> = {
  B: { C: 1 },
  D: [ { E: 2 } ],
}

myDeepReadonlyObject.B = { C: 2 }; // error :)
myDeepReadonlyObject.B.C = 2; // error :)

这太棒了.BB.C 都是只读的.但是,当我尝试修改 D 时...

This is great. Both B and B.C are readonly. When I try to modify D however...

// I'd like this to be an error
myDeepReadonlyObject.D[0] = { E: 3 }; // no error :(

我应该如何编写 DeepReadonly 以便嵌套数组也是只读的?

How should I write DeepReadonly so that nested arrays are readonly as well?

推荐答案

从 TypeScript 2.8 开始,这现在是可能的,并且实际上是条件类型 PR 中的一个示例:https://github.com/Microsoft/TypeScript/pull/21316

As of TypeScript 2.8, this is now possible and actually an example in the PR for Conditional Types: https://github.com/Microsoft/TypeScript/pull/21316

另请参阅条件类型的类型推断说明:https://github.com/Microsoft/TypeScript/pull/21496

Also see the notes on type inference for Conditional Types:https://github.com/Microsoft/TypeScript/pull/21496

我稍微修改了示例以使用只读数组值类型的类型推断,因为我发现 (infer R)[]Array 更清晰code> 但两种语法都有效.我还删除了示例 NonFunctionPropertyNames 位,因为我想在输出中保留函数.

I modified the example slightly to use the type inference for the readonly array value type because I find (infer R)[] clearer than Array<T[number]> but both syntaxes work. I also removed the example NonFunctionPropertyNames bit as I want to preserve functions in my output.

type DeepReadonly<T> =
    T extends (infer R)[] ? DeepReadonlyArray<R> :
    T extends Function ? T :
    T extends object ? DeepReadonlyObject<T> :
    T;

interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}

type DeepReadonlyObject<T> = {
    readonly [P in keyof T]: DeepReadonly<T[P]>;
};

以这种方式执行 DeepReadonly 还保留了可选字段(感谢 Mariusz 让我知道),例如:

Doing DeepReadonly this way also preserves optional fields (thanks to Mariusz for letting me know), e.g.:

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

type RA = DeepReadonly<A>;

// RA is effectively typed as such:
interface RA {
    readonly x?: number;
    readonly y: number;
}

虽然 TS 在某些情况下仍然有一些简单的方法来失去只读性",但这与 C/C++ 风格的 const 值非常接近.

While TS still has some easy ways to lose "readonly-ness" in certain scenarios, this is as close to a C/C++ style const value as you will get.

这篇关于DeepReadonly 对象打字稿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-21 23:05