Reputation: 199
I don't understand this:
const VALUES = {
name: "name",
age: "age",
address: "address",
};
export function getVal(key: string) {
if (key in VALUES) {
// Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; age: string; address: string; }'.
// No index signature with a parameter of type 'string' was found on type '{ name: string; age: string; address: string; }'.ts(7053)
return VALUES[key];
}
return "";
}
The conditional is explicitly making the key
be one of the keys in VALUES
in the true branch. So why is typescript complaining? Wouldn't key in obj
narrow key
to be one of the keys in obj
?
I understand I can do one of two things to fix it:
A/
const VALUES: { [index: string]: string } = {
name: "name",
age: "age",
address: "address",
};
B/
export function getVal(key: keyof typeof VALUES) {
...
}
But what if I want to keep VALUES
type constrained to those keys, and/or the key
param remain as a string
?
EDIT:
As T.J. Crowder pointed out in the comments, perhaps a better "fix" would be:
const VALUES = {
name: "name",
age: "age",
address: "address",
};
function isValidKey(key: string): key is keyof typeof VALUES {
return key in VALUES;
}
export function getVal(key: string) {
if (isValidKey(key)) {
return VALUES[key];
}
return "";
}
Upvotes: 5
Views: 1220
Reputation: 327934
TypeScript supports narrowing via in
operator, but currently a check like key in obj
will only serve to narrow the type of obj
and not the type of key
. Traditionally this would only work when obj
was of a union type, and then "k" in obj
would filter the union to just those members with a known k
key. TypeScript 4.9 added additional narrowing for non-union types in
; so if obj
is not a union, "k" in obj
will narrow obj
to a type where obj.x
is an unknown
property. Neither of these narrowings do anything to key
given a key in obj
check.
The reason this doesn't already happen is because it was never implemented. There is an open feature request at microsoft/TypeScript#43284 asking to narrow the type of key
. It's marked as "Awaiting more feedback", so it is unlikely to get implemented unless there's more engagement on the issue, with 👍 and descriptions of use cases, and why the current workarounds are not acceptable.
Upvotes: 7