Skip to content

Instantly share code, notes, and snippets.

@JeanMeche
Last active August 26, 2022 08:00
Show Gist options
  • Save JeanMeche/d2d4359024dfd32788e5568276d25c35 to your computer and use it in GitHub Desktop.
Save JeanMeche/d2d4359024dfd32788e5568276d25c35 to your computer and use it in GitHub Desktop.
type Id<T> = { [P in keyof T]: T[P] }
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
}
type x = { foo: number, [x: string]: number };
type IsUnknown<T> = [T, unknown] extends [unknown, T] ? true : false;
// https://stackoverflow.com/a/71627376/884123
type ArrayOfTwoOrMore<T> = [T, T, ...T[]];
type RemoveFirst<T extends Array<unknown>> = T extends [unknown, ...infer rest] ? rest : never;
type AllUnionMemberKeys<T> = T extends any ? keyof T : never;
type AB = { a: string } | { b: string }
type ABnever = keyof(AB) // never
type ABKey = AllUnionMemberKeys<AB> // 'a' | 'b'
// https://stackoverflow.com/questions/72771052/get-type-from-nested-object-as-type#72771372
// ========
type BinDigit = "0" | "1"
type OnlyBinDigit<S> =
S extends ""
? unknown
: S extends `${BinDigit}${infer Tail}`
? OnlyBinDigit<Tail>
: never
type BinDigits = string & { __brand: 'onlydigits' }
declare function onlyBinDigit<S extends string>(s: S & OnlyBinDigit<S>): BinDigits;
const a = onlyBinDigit("01010101010011"); // OK
const notBin = onlyBinDigit("010101012"); // NOK
// https://stackoverflow.com/q/72922880/884123
// =====
// A union of functions it is only safe to invoke it with an intesection of parameters which in this case resolves to never
type Foo = ((foo: number) => void) | ((foo: string) => void)
declare const foo: Foo;
foo()
type Boo = ((foo: { a?: string, b: string; }) => void) | ((bar: { b: string, c?: string }) => void)
declare const bar: Boo;
bar({ b: '' })
// === Excess Property check
// The quirk of excess property checks is that for unions, it allows any property from any union constituent to be present in the assigned object literal.
// You can get an error if the union constituents are incompatible one with another:
type Type = {
a: number;
} | {
a: number;
b: number;
} | {
a: number;
b: number;
c: number;
};
const t: Type = { // OK
a: 1,
c: 3
};
// https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#improved-excess-property-checks-in-union-types
// ==== Generic Factory ====
type ConstructorArguments<T> = T extends new (...args: infer P) => any
? P
: never;
class Foo {
constructor(private foo: string, private bar: number) { }
}
export class Factory {
public create<T extends new (...args: Array<any>) => any>(
constr: T,
...params: ConstructorArguments<T>
): InstanceType<T> {
return new constr(...params);
}
public foo() {
this.create(Foo, "foo", 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment