可以创建这样的DeepReadonly
类型:
type DeepReadonly= { readonly [P in keyof T]: DeepReadonly ; }; interface A { B: { C: number; }; D: { E: number; }[]; } const myDeepReadonlyObject: DeepReadonly = { B: { C: 1 }, D: [ { E: 2 } ], } myDeepReadonlyObject.B = { C: 2 }; // error :) myDeepReadonlyObject.B.C = 2; // error :)
这很棒.这两个B
和B.C
是只读的.当我尝试修改D
但是...
// I'd like this to be an error myDeepReadonlyObject.D[0] = { E: 3 }; // no error :(
我应该怎么写,DeepReadonly
以便嵌套数组也是只读的?
从TypeScript 2.8开始,现在可以实现,并且实际上是条件类型的PR中的一个示例:https://github.com/Microsoft/TypeScript/pull/21316
另请参阅条件类型的类型推断说明:https: //github.com/Microsoft/TypeScript/pull/21496
我稍微修改了示例以使用readonly数组值类型的类型推断,因为我发现(infer R)[]
比Array
两个语法更清晰,但两种语法都有效.我还删除了示例NonFunctionPropertyNames
位,因为我想保留输出中的函数.
type DeepReadonly= T extends (infer R)[] ? DeepReadonlyArray : T extends Function ? T : T extends object ? DeepReadonlyObject : T; interface DeepReadonlyArray extends ReadonlyArray > {} type DeepReadonlyObject = { readonly [P in keyof T]: DeepReadonly ; };
以这种方式执行DeepReadonly也会保留可选字段(感谢Mariusz让我知道),例如:
interface A { x?: number; y: number; } type RA = DeepReadonly; // RA is effectively typed as such: interface RA { readonly x?: number; readonly y: number; }
虽然在某些情况下TS仍然有一些简单的方法可以丢失"readonly-ness",但这const
与你将获得的C/C++风格值接近.