Skip to content

Instantly share code, notes, and snippets.

@NaridaL
Last active November 9, 2017 19:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NaridaL/2c2a0775f38f551bdce5899913f6d1b9 to your computer and use it in GitHub Desktop.
Save NaridaL/2c2a0775f38f551bdce5899913f6d1b9 to your computer and use it in GitHub Desktop.

Pseudo-Variadic arguments aka How do I change the return type of a function?

Until microsoft/TypeScript#5453 is implemented, you'll need to create multiple overloads, one for each number of arguments. For example, this is the type definition of a function which takes a function and returns a function with the same arguments but the result wrapped in a Promise.

declare function wrapPromise<R>(f: () => R): () => Promise<R> 
declare function wrapPromise<A1, R>(f: (a1: A1) => R): (a1: A1) => Promise<R>
declare function wrapPromise<A1, A2, R>(f: (a1: A1, a2: A2) => R): (a1: A1, a2: A2) => Promise<R>
declare function wrapPromise<A1, A2, A3, R>(f: (a1: A1, a2: A2, a3: A3) => R): (a1: A1, a2: A2, a3: A3) => Promise<R>
declare function wrapPromise<A1, A2, A3, A4, R>(f: (a1: A1, a2: A2, a3: A3, a4: A4) => R): (a1: A1, a2: A2, a3: A3, a4: A4) => Promise<R>
// etc. 8 arguments should be enough for everyone :-P

What's the difference between the types [Foo] and Foo[]

[Foo] is a 1-element tuple type, i.e. arrays of length 1 containing a Foo can be assigned to it. Handbook Foo[] is a an array of Foos, i.e. any length arrays can be assigned.

Is there a subtraction type?

Not built-in, see the related TS issue #4183

It is possible to hack this in manually, see https://github.com/NaridaL/subtractiontype.ts

How do I create a string union type and a corresponding array?

Awkwardly.

Option 1 (note that ['T'] is the indexed access operator):

// note that the argument o needs to be an immediate array of string literals, 
// otherwise the type inference will not work.
export function StrUnionHelper<T extends string>(o: Array<T>): Array<T> & { T: T } {
    return o as any
}
// variable/type:
const STRINGS_ARRAY = StrUnionHelper(["a", "b", "c"])
type STRINGS_UNION = (typeof STRINGS_ARRAY)['T'] // indexed access operator
//  class/fields
class Class {
    STRINGS_FIELD = StrUnionHelper(["a", "b", "c"])
    STRING_FIELD: Class['STRINGS_FIELD']['T'] = "a"
    static STRINGS_FIELD_STATIC = StrUnionHelper(["a", "b", "c"])
    static STRING_FIELD_STATIC: (typeof Class)['STRINGS_FIELD_STATIC']['T']
}

Option 2:

// do not explicitly type the object
const helperObject = {
    a: true,
    b: true,
    z: true,
}
type STRINGS = keyof typeof helperObject
const STRINGS = Object.keys(helperObject)

Why aren't my types loading?

  • For @types packages: Are typeRoots or types set in tsconfig.json? Both of these can prevent types from being loaded.

  • For global declaration files (i.e. you aren't importing them) which are not in @types (local types or types bundled in packages), make sure they are being included in your compilation, either by adding them to includes section of your tsconfig or by referencing them from files which need them.

  • Use tsc --listFiles to check if declaration files are being loaded. Use tsc --traceResolution to see where TS is looking for module declarations. (See compiler options)

  • Restart VS Code. Sometimes the language service is behind. Run tsc from the command line to check if TS really can't find the types.

  • Do the symbols you're trying to reference actually exist? Check the declaration file to make sure you don't have a typo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment