Created
April 9, 2018 07:45
-
-
Save esamattis/b100b5e6387934d9dffa93da7eabd349 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type DeepReadonly<T> = | |
T extends [infer A] ? DeepReadonlyObject<[A]> : | |
T extends [infer A, infer B] ? DeepReadonlyObject<[A, B]> : | |
T extends [infer A, infer B, infer C] ? DeepReadonlyObject<[A, B, C]> : | |
T extends [infer A, infer B, infer C, infer D] ? DeepReadonlyObject<[A, B, C, D]> : | |
T extends [infer A, infer B, infer C, infer D, infer E] ? DeepReadonlyObject<[A, B, C, D, E]> : | |
T extends [infer A, infer B, infer C, infer D, infer E, infer F] ? DeepReadonlyObject<[A, B, C, D, E, F]> : | |
T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G] ? DeepReadonlyObject<[A, B, C, D, E, F, G]> : | |
T extends (infer A)[] ? DeepReadonlyArray<A> : | |
T extends Function ? T : // can change to never to forbid functions | |
T extends Map<infer U, infer V> ? ReadonlyMap<DeepReadonlyObject<U>, DeepReadonlyObject<V>> : | |
T extends Set<infer U> ? ReadonlySet<DeepReadonlyObject<U>> : | |
T extends object ? DeepReadonlyObject<T> : | |
T | |
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} | |
type DeepReadonlyObject<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> } | |
type DeepTestType = DeepReadonly<{ | |
a: string | |
b: number[] | |
c: { d: string, e: number[], f: [number, { g: string, h: number }] } | |
i: [number, string, boolean] | |
j: { id: number, name: string }[] | |
k: Set<number> | |
l: Map<{ id: number, name: string }, { age: number }> | |
m(): void | |
n: Symbol | |
o: Promise<void> | |
}> | |
const record = { id: 123, name: 'zxc' } | |
const deepTest: DeepTestType = { | |
a: 'asdf', | |
b: [123, 234], | |
c: { d: 'zxc', e: [1, 2, 3], f: [1, { g: 'iop', h: 789 }] }, | |
i: [1, 'a', true], | |
j: [{ id: 1, name: 'c' }], | |
k: new Set([1, 2, 3]), | |
l: new Map([ | |
[record, { age: 789 }] | |
]), | |
m() { console.log('m says mmm') }, | |
n: Symbol(), | |
o: Promise.resolve() | |
} | |
console.log(deepTest.a) // pass | |
deepTest.a = 'zxcv' // fail | |
console.log(deepTest.b[0]) // pass | |
deepTest.b[0] = 789 // fail | |
deepTest.b[1] = 890 // fail | |
console.log(deepTest.c.d) // pass | |
deepTest.c.d = 'asd' // fail | |
console.log(deepTest.c.f[0]) // pass | |
deepTest.c.f[0] = 'asd' // fail | |
console.log(deepTest.c.f[1].g) // pass | |
deepTest.c.f[1].g = 'zxc' // fail | |
console.log(deepTest.i[1]) // pass | |
console.log(Math.pow(deepTest.i[0], 1) // pass (doesn't union tuple) | |
deepTest.i[1] = 'zxc' // fail | |
console.log(deepTest.j[0].id) // pass | |
deepTest.j[0].id = 789 // fail | |
console.log(deepTest.k) // pass | |
deepTest.k.add(789) // fail | |
console.log(deepTest.l.get(record).age) // pass | |
deepTest.l.get(record).age = 1 // fail | |
deepTest.l.set({ id: 789, name: 'blah' }, { age: 567 }) // fail | |
for (let key of deepTest.l.keys()) { | |
console.log(key.name) // pass | |
key.name = 'zxc' // fail | |
} | |
deepTest.m() // pass | |
deepTest.m = () => console.log('n says nnn') // fail | |
console.log(deepTest.n) // pass | |
deepTest.n = Symbol() // fail | |
deepTest.o.then(() => console.log('hello')) // pass | |
deepTest.o = Promise.resolve() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment