Created
September 21, 2017 15:23
-
-
Save gcanti/da641d57dc6ebbdd0b1f4b2eb7e3394e to your computer and use it in GitHub Desktop.
Type-safe get, set, remove, pick, insert with TypeScript
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
import { ObjectOmit } from 'typelevel-ts' | |
const get = <O, K extends keyof O>(k: K, o: O): O[K] => o[k] | |
const set = <O, K extends keyof O>(k: K, v: O[K], o: O): O => Object.assign({}, o, { [k as any]: v }) | |
const remove = <O, K extends keyof O>(k: K, o: O): ObjectOmit<O, K> => { | |
const copy: any = Object.assign({}, o) | |
delete copy[k] | |
return copy | |
} | |
const pick = <O, K extends keyof O>(ks: [K], o: O): Pick<O, K> => { | |
const copy: any = {} | |
ks.forEach(k => { | |
copy[k] = o[k] | |
}) | |
return copy | |
} | |
const insert = <O>() => <K extends keyof O>(k: K, v: O[K], o: ObjectOmit<O, K>): O => | |
Object.assign({}, o, { [k as any]: v }) as any | |
// | |
// tests | |
// | |
const get1: number = get('a', { a: 1 }) // ok | |
console.log(get1) // => 1 | |
// const get2: string = get('a', { a: 1 }) // error | |
// const get3: string = get('b', { a: 'sdf' }) // error | |
const set1 = set('a', 2, { a: 1 }) // ok | |
console.log(set1) // => { a: 2 } | |
// const set2 = set('a', 'foo', { a: 1 }) // error | |
// const set3 = set('b', 2, { a: 1 }) // error | |
// ugly displayed type though | |
/* | |
const remove1: Pick<{ | |
a: number; | |
b: string; | |
c: boolean; | |
}, "a" | "c"> | |
*/ | |
const remove1 = remove('b', { a: 1, b: 'foo', c: true }) | |
console.log(remove1) // => { a: 1, c: true } | |
// const remove2 = remove('b', { a: 1, c: true }) // error | |
const pick1 = pick(['a'], { a: 1, b: 'foo', c: true }) | |
console.log(pick1) // => { a: 1 } | |
const pick2 = pick(['a', 'c'], { a: 1, b: 'foo', c: true }) | |
console.log(pick2) // => { a: 1, c: true } | |
// const pick3 = pick(['d'], { a: 1, b: 'foo', c: true }) // error | |
type MyRecord = { a: number; b: string; c: boolean } | |
const myinsert = insert<MyRecord>() | |
const insert1 = myinsert('a', 1, { b: 'foo', c: true }) | |
console.log(insert1) // => { b: 'foo', c: true, a: 1 } | |
// const insert2 = myinsert('d', 1, { b: 'foo', c: true }) // error | |
// const insert3 = myinsert('a', 2, { a: 1, b: 'foo', c: true }) // error | |
const x = { a: 1, b: 'foo', c: true } | |
const insert4 = myinsert('a', 2, x) // NO error |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment