Reputation: 648
I have the following types
type Type = {
prop1: number;
prop2: string;
prop3: someOtherType
}
type Props = keyof Type
now I know you can use an "indexed access type" to get the type of propN, i.e. type Num = Type["prop1"]
, however I would like to use the following in a function
function(p: Props) {
// ...
let something = somethingElse as Type[p]
// Typescript can't infer the type
// ...
}
so that when i call
let a = function("prop1");
// a should be of type number
However that is not possible, and throws
'p' refers to a value, but is being used as a type here. Did you mean 'typeof p'?
however if I use typeof p
, then Type[typeof p]
gives me the union type number | string | someOtherType
.
Is there some way to fix this. I have tried to look at using generices, but it doesn't seem possible.
Upvotes: 0
Views: 109
Reputation: 42188
When you call typeof p
you get the Typescript type of the Javascript variable p
. You have said right here function(p: Props)
that the type of p
is Props
. That type means that it can be any of the keys of Props
.
You must use a generic if you want your code to know which key p
is. Otherwise that information is discarded and the type of p
is widened to Props
by function(p: Props)
.
You can use your indexed access type assertion if the type of p
is generic.
function myFunc<P extends Props>(p: P) {
// ...
let something = somethingElse as Type[P]
// Typescript can't infer the type
// ...
}
But you might not even need to assert with as
if everything is typed properly.
type Type = {
prop1: number;
prop2: string;
}
type Props = keyof Type
function myFunc<P extends Props>(p: P) {
const type: Type = { prop1: 0, prop2: "" };
return type[p]; // type is inferred as `Type[P]`
}
const one = myFunc("prop1"); // type number
const two = myFunc("prop2"); // type string
Upvotes: 1
Reputation: 6853
More complete example:
type ValueOf<T> = T[keyof T];
type Type = {
prop1: number;
prop2: string;
prop3: boolean;
}
type Props = keyof Type;
function foo<T extends Props>(p: T): Type[T] {
let something = "";
return something as Type[T];
}
const a = foo("prop1"); // a is number
const b = foo("prop2"); // b is string
const c = foo("prop3"); // c is boolean
Upvotes: 1
Reputation: 4611
So I think what you are trying to achieve can be done using a generic function like so:
function foo<T extends keyof Type>(p: T) {
let something = somethingElse as T
}
Upvotes: 2