admin管理员组文章数量:1398797
Playground
In TypeScript, how do you "assert" that a keyof type is not readonly, when technically it possibly is?
class Foo {
x = 1
readonly y = 2
}
const foo = new Foo()
const k = 'x' as keyof Foo
foo[k] = 3
In this case, I know for a fact the key is not readonly, but casting to "any" doesn't solve it. My only solution so far is casting (foo as any)[k] = 3
but surely there's a better way?
Playground
In TypeScript, how do you "assert" that a keyof type is not readonly, when technically it possibly is?
class Foo {
x = 1
readonly y = 2
}
const foo = new Foo()
const k = 'x' as keyof Foo
foo[k] = 3
In this case, I know for a fact the key is not readonly, but casting to "any" doesn't solve it. My only solution so far is casting (foo as any)[k] = 3
but surely there's a better way?
2 Answers
Reset to default 3TypeScript features a Readonly utility type, which is designed to mark all Record keys as readonly. To achieve the inverse, we can use the following syntax:
type Writeable<T> = { -readonly [K in keyof T]: T[K] }
Then, we can cast our foo
type:
class Foo {
x = 1
readonly y = 2
}
const foo = new Foo()
const k = 'x'
(foo as Writeable<Foo>)[k] = 3;
Alternatively, if you want only to get writeable keys for a record:
type EqualMutability<A, B> = (<T>() => T extends A ? true : false) extends
(<T>() => T extends B ? true : false) ? true : false
type IsReadonly<R, K extends keyof R> = EqualMutability<
{ readonly [S in K]: R[K] },
{ [S in K]: R[K] }
>
type PickWritable<R> = Pick<R, { [K in keyof R]: IsReadonly<R, K> extends false ? K : never }[keyof R]>
const k: keyof PickWritable<Foo> = "x"
foo[k] = 3
You need to narrow your keys to proper writable keys or make the readonly properties to support a runtime check:
Playground
class Foo {
x = 1
get y(){ return 2;}
}
const foo = new Foo()
const k = 'x' as keyof Foo
// option 1
if(k === 'x'){
foo[k] = 3
}
// option 2 (you need to use getters)
const canWrite = <T extends object, K extends keyof T>(obj: T, key: K): obj is T & {-readonly[k in K]: T[k]} => {
const desc = Object.getOwnPropertyDescriptor(obj, key) ?? {};
if(desc.get && !desc.set) return false;
if(!desc.set && !desc.writable) return false;
return true;
}
if(canWrite(foo, k)){
console.log('can write!');
foo[k] = 3;
}
if(!canWrite(foo, 'y')){
console.log('cannot write!');
}
本文标签: How do you cast a potentially readonly key to readwrite key in TypeScriptStack Overflow
版权声明:本文标题:How do you cast a potentially readonly key to readwrite key in TypeScript? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744685586a2619678.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论