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.