Home > Mobile >  How to get TypeScript to allow optional parameters?
How to get TypeScript to allow optional parameters?

Time:09-17

The below code works as intended in JavaScript, but when compiling it to TypeScript I get the error

t.ts:11:34 - error TS2554: Expected 1 arguments, but got 6.    
11 console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 2))
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

t.ts:14:34 - error TS2554: Expected 1 arguments, but got 6.
14 console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 4))
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Question

How can I get this function to work in TypeScript?

var obj = [{
  "category1": {
    nested: {
      a: 'string',
      b: [69, 13, 15]
    }
  },
  "category2": "2",
}];

console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 2))
// print 15

console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 4))
// print undefined at key 4

function where_undefined(obj) {
  var args = Array.prototype.slice.call(arguments)
  args.shift();
  while (args.length) {
    var arg = args.shift();
    if (obj[arg] === undefined) {
      console.log("undefined at key "   arg);
      break;
    } else {
      obj = obj[arg];
    }
  }
  return obj;
}

CodePudding user response:

First, like @A_A has described, we should be using rest parameters:

function where_undefined(obj: any, ...args: PropertyKey[]) {

We also need to give them types. I have used any for obj here, because if we had used unknown, we'd get many more unnecessary errors in the function body. PropertyKey is a built-in type that represents all possible types for keys (string | number | symbol).

Since we're using rest parameters, we don't need this bit:

var args = Array.prototype.slice.call(arguments)
args.shift();

All this is doing is getting the same result as args in our new code.

The next change is here:

const arg = args.shift()!;

We use ! to assert that this cannot be undefined (since undefined cannot be used as a key). If we did not use an assertion here, we'd get errors when we try to use arg as a key:

obj[arg] // ! Type 'undefined' cannot be used as an index type.

However, now when you give it an object, it always returns any, no matter what the type of the object was, so we'll go back and change any to use a generic:

function where_undefined<T>(obj: T, ...args: PropertyKey[]): T {

But with this change, we get even more errors in the body. We can "ignore" these by changing this to an external signature:

function where_undefined<T>(obj: T, ...args: PropertyKey[]): T {
function where_undefined(obj: any, ...args: PropertyKey[]) {

The final result can be seen in this playground.

  • Related