Javascript typescript中的Object.freeze/Object.seal
Typescript中是否建议使用Javascript typescript中的Object.freeze/Object.seal,javascript,typescript,Javascript,Typescript,Typescript中是否建议使用Object.freeze,或者是否有其他方法确保对象保持不变 因为const只保护实例,而不保护属性,这显然不是我要寻找的答案 是否有其他方法确保对象保持不变 这取决于你想要的保险水平 如果您想确保没有使用者(无论是TypeScript还是JavaScript代码)可以在运行时修改对象属性,object.freeze就是这样做的 如果编译时检查足够,例如,当所有使用者代码都保证仅为TypeScript和typechecked时,您可以使用,它接受一个对象类型并
Object.freeze
,或者是否有其他方法确保对象保持不变
因为const
只保护实例,而不保护属性,这显然不是我要寻找的答案
是否有其他方法确保对象保持不变
这取决于你想要的保险水平
如果您想确保没有使用者(无论是TypeScript还是JavaScript代码)可以在运行时修改对象属性,
object.freeze
就是这样做的
如果编译时检查足够,例如,当所有使用者代码都保证仅为TypeScript和typechecked时,您可以使用,它接受一个对象类型并生成所有。实际上,Object.freeze()
在中声明为返回其参数的修改类型ReadOnly
:
freeze<T>(o: T): Readonly<T>;
而
Object.seal()
是唯一的方法。如果您想进行运行时和编译时检查,您可以这样做
export const frozen:Readonly<{a:number}> = Object.freeze({a:1});
对象和函数上的递归Object.freeze()添加只读类型:
export const deepFreeze = <T>(source: T, freezeParent = true): DRo<T> => {
if (freezeParent) Object.freeze(source)
Object.getOwnPropertyNames(source).forEach(function(prop) {
if (
Object.prototype.hasOwnProperty.call(source as any, prop) &&
(source as any)[prop] !== null &&
(typeof (source as any)[prop] === 'object' || typeof (source as any)[prop] === 'function')
) {
if (Object.isFrozen((source as any)[prop])) {
deepFreeze((source as any)[prop], false)
} else {
deepFreeze((source as any)[prop], true)
}
}
})
return source as DRo<T>
}
type DRo<T> = T extends (infer R)[] ? DRoArr<R> : T extends Function ? T : T extends object ? DRoObj<T> : T
interface DRoArr<T> extends ReadonlyArray<DRo<T>> {}
type DRoObj<T> = {
readonly [P in keyof T]: DRo<T[P]>
}
export const deepFreeze=(来源:T,freezeParent=true):DRo=>{
如果(冻结父对象)对象。冻结(源)
Object.getOwnPropertyNames(源).forEach(函数(prop){
如果(
Object.prototype.hasOwnProperty.call(源代码为any,prop)&&
(源作为任何源)[prop]!==null&&
(typeof(源代码为任意)[prop]=='object'| | typeof(源代码为任意)[prop]=='function')
) {
if(Object.isfronged((源代码为any)[prop])){
deepFreeze((来源为任何)[prop],false)
}否则{
deepFreeze((来源为任何)[prop],true)
}
}
})
返回源为DRo
}
类型DRo=T扩展(推断R)[]?DRoArr:T扩展函数?T:T扩展对象?DRoObj:T
接口DRoArr扩展只读数组{}
类型DRoObj={
只读[P in keyof T]:DRo
}
Object.freeze包括Seal。最简单的解决方案:as const
这代表了对所有级别的对象或数组的不变性的深度冻结
const a = {
b: 1,
c: {d: 'e'},
f: ['g', 'h'],
} as const
所有这些都不允许覆盖
a = 'not'
a.b = 'going'
a.c.d = 'to'
a.f[1] = 'change'
All result in error "TS2540: Cannot assign to '<name>' because it is a read-only property."
带不可变的不可变参数
这与常量的作用相同,可以深度冻结参数
// Add this and make it reuseable
type Immutable<T> = {
readonly [K in keyof T]: Immutable<T[K]>
}
//添加此项并使其可重用
类型不可变={
只读[K in keyof T]:不可变
}
在
中定义类型,即不可变
\u方法=(a:不可变)=>{
//这会引起抱怨
a、 b.c.d[0]=“”
}
也许?对象。冻结是一个运行时概念。TypeScript只在JavaScript上运行,所以…。。@DanielA.White,很自然地,我说的是编译时检查,代码中没有Object.freeze
a = 'not'
a.b = 'going'
a.c.d = 'to'
a.f[1] = 'change'
All result in error "TS2540: Cannot assign to '<name>' because it is a read-only property."
type a = typeof a[keyof typeof a]
// Add this and make it reuseable
type Immutable<T> = {
readonly [K in keyof T]: Immutable<T[K]>
}
_method = (a: Immutable<{b:{c:{d:[string]}}}>) => {
// This will complain
a.b.c.d[0] = ""
}