Reputation: 4685
I want to write a simple function that looks like this
const options = {
option1: "option1",
option2: "option2",
option3: "option3",
} as const;
function getOption(str: string) {
if (options[str]) {
/**
* Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly option1: "option1"; readonly option2: "option2"; readonly option3: "option3"; }'.
* No index signature with a parameter of type 'string' was found on type '{ readonly option1: "option1"; readonly option2: "option2"; readonly option3: "option3"; }'.ts(7053)
*/
return options[str];
}
return "defaultOption";
}
Now, I know I can solve it like this
const options = {
option1: "option1",
option2: "option2",
option3: "option3",
} as const;
function getOption(str: keyof typeof options) {
if (options[str]) {
// Solved! No warning!
return options[str];
}
return "defaultOption";
}
But it seems like I'm lying to my code...
For example, if I write something like this
function isArray(arg: any[]) {
return Array.isArray(arg);
}
It will be weird to use this util because these two reasons
And here is another example:
Suppose I want to get the 'defaultOption'
by passing argument null
, it will be so weird
// TypeScript yells!
// Argument of type 'null' is not assignable to parameter of type '"option1" | "option2" | "option3"'.ts(2345)
console.log(getOption(null));
// => 'defaultOption'
I will have to do this to suppress the warning
// No more warning.
// Making null as any is weird
getOption(null as any);
// => 'defaultOption'
As you can see, I have to explicitly convert the null
as any
in order to get my 'defaultOption'
Is there any way I can improve my getOption
util?
Upvotes: 3
Views: 243
Reputation: 370639
Ideally, you'd want to type getOption
's argument to be a key of the options, to require callers to pass a sensible argument. But if you want to permit any argument may be passed to getOption
, including a key, or a generic string, or any value at all like null
, then type the argument as unknown
, then have TS narrow down whether the argument is one of options
keys:
function getOption(str: unknown) {
if (str === 'option1' || str === 'option2' || str === 'option3') {
return options[str];
}
return "defaultOption";
}
Upvotes: 1