DeepReadonly对象打字稿 [英] DeepReadonly Object Typescript

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

问题描述

可以这样创建DeepReadonly类型:

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中条件类型的示例:

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<T[number]>更清晰,但是两种语法都可以.我还删除了示例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对象打字稿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆