Skip to content

Instantly share code, notes, and snippets.

@jfet97
Last active May 5, 2022 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfet97/e446840461985534b41e66ddaa33393f to your computer and use it in GitHub Desktop.
Save jfet97/e446840461985534b41e66ddaa33393f to your computer and use it in GitHub Desktop.
as const without as const
// is always the extends keyword that makes the difference, enabling the narrow infering
type Narrowable = string | number | boolean | symbol | undefined | null | void;
declare function wrongKeepLiteralTypes(x: Narrowable): Narrowable;
declare function keepLiteralTypes<T extends Narrowable>(x: T): T;
wrongKeepLiteralTypes(1); // Narrowable
keepLiteralTypes(1); // 1
//
// preserve tuple types by using the empty tuple (or using [...T])
declare function numberTuple<T extends [] | number[]>(t: T): T;
numberTuple([1, 2, 3]); // is [number, number, number] instead of number[]
// N is not inferred because it isn't in the arguments list, but the way TypeScript will infer T
// has changed because N is used into the 'extends' clause of T
declare function narrowableTuple<N extends Narrowable, T extends [] | N[]>(t: T): T;
narrowableTuple([1, 2, 3]); // we got [1, 2, 3]
//
// same power as 'as const', but no readonly
// 'N' is for literals
// 'object' is needed to allow properties that are objects themselves, including 'N[]' and 'any[]'
// '[]' is for tuple > array
// '{ [k: PropertyKey]: T }' is for nested structures
declare function asConstNoReadonly<N extends Narrowable, T extends N | object | [] | { [k: PropertyKey]: T }>(x: T): T;
asConstNoReadonly(123) // 123
asConstNoReadonly(["this", "is", "a"]) // ["this", "is", "a"]
asConstNoReadonly(["this", "is", "a", { a: 7 }]) // ["this", "is", "a", { a: 7; }]
asConstNoReadonly({ a: 7 }) // { a: 7; }
asConstNoReadonly({ a: { b: 43, c: ["this", "is", "a", "tuple", { oh: "yes"} ] } })
// { a: { b: 43; c: ["this", "is", "a", "tuple", { oh: "yes"; }]; }; }
// only objects
declare function asConst<N extends Narrowable, T extends { [k: PropertyKey]: N | [] | T | {} }>(x: T): T;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment