Last active
May 18, 2020 21:36
-
-
Save cleoold/78a55b79d98e93a0b2572626224065d1 to your computer and use it in GitHub Desktop.
remember type knowledge
This file contains hidden or 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
/** https://www.typescriptlang.org/docs/handbook/advanced-types.html */ | |
/** intersection type */ | |
/** returns a new object with properties coming from two given objects */ | |
const merge = <T extends object, S extends object>(first: T, second: S): T & S => { | |
const res: Partial<T & S> = {}; | |
for (const prop in first) | |
if (first.hasOwnProperty(prop)) | |
(<T>res)[prop] = first[prop]; | |
for (const prop in second) | |
if (second.hasOwnProperty(prop)) | |
(<S>res)[prop] = second[prop]; | |
return <T & S>res; | |
} | |
/** type guard */ | |
/** checks if x is number */ | |
const isNumber = (x: any): x is number => | |
typeof x === 'number'; | |
/** type alias */ | |
type Tree<T> = { | |
value: T, | |
nodes: Tree<T>[] | |
}; | |
type LList<T> = T & { | |
next: LList<T> | null | |
}; | |
/** index type */ | |
type T001 = keyof { a: string, b: number } /** "a" | "b" */ | |
/** gets o[propName] */ | |
const getProp = <T, K extends keyof T>(o: T, propName: K): T[K] => | |
o[propName]; | |
/** creates list of mapped values given property names */ | |
const pluck = <T, K extends keyof T>(o: T, propNames: K[]): T[K][] => | |
propNames.map(n => o[n]); | |
/** object with string or number as keys, T as values */ | |
type Dict<T> = { | |
[key: string]: T | |
}; | |
type T002<T> = keyof Dict<T>; /** string | number */ | |
type T003<T> = Dict<T>[0]; /** T */ | |
type T004<T> = Dict<T>['0']; /** T */ | |
/** object with number as keys, T as values */ | |
type Arry<T> = { | |
[key: number]: T | |
}; | |
type T005<T> = keyof Arry<T>; /** number */ | |
type T006<T> = Dict<T>[0]; /** T */ | |
/** mapped type */ | |
/** type of object with readonly properties */ | |
type MyReadonly<T> = { | |
readonly [K in keyof T]: T[K] | |
}; | |
/** type of object with optional properties */ | |
type MyPartial<T> = { | |
[K in keyof T]?: T[K] | |
}; | |
/** type of object with nullable properties */ | |
type MyNullableObject<T> = { | |
[K in keyof T]: T[K] | null | |
}; | |
/** pick some keys K from type T */ | |
type MyPick<T, K extends keyof T> = { | |
[P in K]: T[P] | |
}; | |
type T007 = MyPick<{ a: string, b: string, c: string }, 'a' | 'b'>; /** { a: string, b: string } */ | |
/** make type with keys K and values T */ | |
type MyRecord<K extends keyof any, T> = { | |
[P in K]: T; | |
}; | |
type T008 = MyRecord<'a' | 'b' | 'c', number>; /** { a: number, b: number, c: number } */ | |
/** proxify */ | |
type ProxifiedValue<V> = { | |
get(): V, | |
set(v: V): void | |
}; | |
type ProxifiedObject<T extends object> = { | |
[P in keyof T]: ProxifiedValue<T[P]> | |
}; | |
const proxify = <T extends object>(o: T): ProxifiedObject<T> => { | |
const res = {} as ProxifiedObject<T>; | |
for (const k in o) /** const k: Extract<keyof T, string> */ | |
if (o.hasOwnProperty(k)) | |
res[k] = { | |
get: () => o[k], | |
set: v => o[k] = v | |
} | |
return res; | |
} | |
const unproxify = <T extends object>(po: ProxifiedObject<T>): T => { | |
const res = {} as any; | |
for (const k in po) | |
res[k] = po[k].get(); | |
return res; | |
}; | |
/** conditional type */ | |
type TypeName<T> = | |
T extends string ? 'string' : | |
T extends number ? 'number' : | |
T extends boolean ? 'boolean' : | |
T extends symbol ? 'symbol' : | |
T extends bigint ? 'bigint' : | |
T extends undefined ? 'undefined' : | |
T extends Function ? 'function' : | |
'object'; | |
type T009 = TypeName<string | string[] | null | undefined>; /** "string" | "undefined" | "object" */ | |
/** Remove types from T that are assignable to U */ | |
type MyExclude/*Diff*/<T, U> = T extends U ? never : T; | |
type T010 = MyExclude<'a' | 'b' | 'c' | 0 , 'b' | number>; /** "a" | "c" */ | |
// | |
/** extracts from T all properties that are assignable to U */ | |
type MyExtract/*Filter*/<T, U> = T extends U ? T : never; | |
// | |
type T011 = MyExtract<'a' | 'b' | 'c' | 0 , 'b' | number>; /** 0 | "b" */ | |
type T012<O> = MyExtract<keyof O, string> /** string properties of O */ | |
/** remove null and undefined from T */ | |
type MyNonNullable<T> = MyExclude<T, null | undefined>; | |
/** make object's properties non nullable */ | |
type MyNonNullableObject<T> = { | |
[K in keyof T]: MyNonNullable<T[K]> | |
}; | |
/** make object's all fields required (can't ?) */ | |
type MyRequired<T> = { | |
[K in keyof T]-?: T[K] | |
}; | |
type T013 = MyRequired<MyNonNullableObject<MyNullableObject<MyPartial<{ p: string }>>>> /** { p: string } */ | |
/** names of methods of an object (result is union) */ | |
type FunctionPropertyNames<T> = { | |
[K in keyof T]: T[K] extends Function ? K : never | |
}[keyof T]; | |
/** names of non-function properties of an object */ | |
type NonFunctionPropertyNames<T> = MyExclude<keyof T, FunctionPropertyNames<T>>; | |
/** methods of an object */ | |
type FunctionProperties<T> = MyPick<T, FunctionPropertyNames<T>>; | |
/** non-methods of an object */ | |
type NonFunctionProperties<T> = MyPick<T, NonFunctionPropertyNames<T>>; | |
/** inference */ | |
/** parameter type of function */ | |
type MyParameters<F extends Function> = F extends (..._: infer A) => any ? A : never; | |
/** return type of function */ | |
type MyReturnType<F extends Function> = F extends(..._: any) => infer R ? R : never; | |
/** parameter type of constructor */ | |
type MyConstructorParameters<F extends new (..._: any) => any> = F extends new (..._: infer A) => any ? A : never; | |
/** return type of constructor */ | |
type MyInstanceType<F extends new (..._: any) => any> = F extends new (..._: any) => infer C ? C : never; | |
// | |
type T014 = MyInstanceType<typeof Boolean>; /** Boolean */ | |
/** what value that matters will I get? */ | |
type Unpacked<T> = | |
T extends (infer U)[] ? U : | |
T extends (..._: any) => infer U ? U : | |
T extends { new: (..._: any) => infer U } ? U : | |
T extends Promise<infer U> ? U : | |
T; | |
const T016 = () => Promise.resolve([ 0, 1, 2, 4, 8, 16, 32 ]); | |
type T015 = Unpacked<Unpacked<Unpacked< typeof T016 >>>; /** number */ | |
/** question */ | |
type Ex<T, U> = T extends U ? never : T; | |
/** type epic = "c" */ | |
type epic = Ex<'a'|'b'|'c', 'a'|'b'>; | |
/** type unepic = "a" | "b" | "c" */ | |
type unepic = ('a'|'b'|'c') extends ('a'|'b') ? never : ('a'|'b'|'c'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment