Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript Function/Object parameters

Why is typescript ES6 not detecting that objects are not functions?

find: (collection: string, query: object, sortQuery = {}, cb?: Function)  => {
    socketManager.call('find', collection, query, sortQuery, cb);
}

Based off this function, you would assume that this would fail:

this._services._socket.methods.find('vendors', {type: 'repair'}, (errVen, resVen) => {}

Since there is no sortQuery object but instead a callback function. This is not giving me any type of error and means that typescript is allowing the callback as the object type.

How do I ensure this results in an error?

like image 563
user1779362 Avatar asked Nov 27 '18 16:11

user1779362


1 Answers

With TypeScript Conditionals (TS v2.8), we can use Exclude to exclude Functions from the object type using Exclude<T, Function>:

let v = {
  find: <T extends object>(collection: string, query: object, sortQuery: Exclude<T, Function>, cb?: (a: string, b: string) => void) => {
  }
}

// Invalid
v.find('vendors', { type: 'repair' }, (a, b) => { })
v.find('vendors', { type: 'repair' }, 'I am a string', (a, b) => { })

// Valid
v.find('vendors', { type: 'repair' }, { dir: -1 })
v.find('vendors', { type: 'repair' }, { dir: -1 }, (a, b) => { })

A default parameter value can then be set like this:

sortQuery: Exclude<T, Function> = <any>{}

As you can see in the image below, errors are thrown for the first two calls to find, but not the second two calls to find:

TypeScript Exclude

The errors that then display are as follows:

  • [ts] Argument of type '(a, b) => void' is not assignable to parameter of type 'never'. [2345]
  • [ts] Argument of type '"I am a string"' is not assignable to parameter of type 'object'. [2345]
like image 154
Get Off My Lawn Avatar answered Sep 28 '22 14:09

Get Off My Lawn