To dynamically get an interface or type alias property value type from conditional types, you can use the infer
keyword followed by declaring a generic type name
wherever you need to get the value from and then using that value as the truthy value in the conditional type check in TypeScript.
TL;DR
// a generic conditional type
type GetSalaryType<T> = T extends { salary: infer value } ? value : never;
// an interface where the salary
// property is `string` type
interface Person {
name: string;
salary: string;
}
// an interface where the salary
// property is `number` type
interface Person2 {
name: string;
salary: number;
}
// an interface where the salary
// property is an `array of string` type
interface Person3 {
name: string;
salary: string[];
}
// get the type of the `salary` property
// from the all the above interfaces
type SalaryType = GetSalaryType<Person>; // string
type SalaryType2 = GetSalaryType<Person2>; // number
type SalaryType3 = GetSalaryType<Person3>; // string[]
For example, first, let's consider a small scenario where we need to choose between the type string
and the number
type by checking if the interface
or the type alias
contains a property called salary
.
So in this case the better way is to use a conditional type
and make the whole type into a generic type alias
.
It can be done like this,
// a generic conditional type
type GetSalaryType<T> = T extends { salary: string } ? string : never;
Now let's create an interface called Person
with properties called name
and salary
having the type of string
.
It can be done like this,
// a generic conditional type
type GetSalaryType<T> = T extends { salary: string } ? string : never;
// a simple interface called Person
interface Person {
name: string;
salary: string;
}
Now let's pass the Person
interface to the GetSalaryType
generic conditional type like this,
// a generic conditional type
type GetSalaryType<T> = T extends { salary: string } ? string : never;
// a simple interface called Person
interface Person {
name: string;
salary: string;
}
// get the type of the `salary` property
// from the `Person` interface
type SalaryType = GetSalaryType<Person>; // string
Now if you hover over the SalaryType
type you can see that the type is of string
that is correct and satisfies our needs in this case.
But we know that salary
can have many forms like string
, number
or even an array
of salaries. If we pass a type where the salary
type is number
to the GetSalaryType
then also we will get the type of string
in the SalaryType
type alias which may not suit our needs.
So to make the GetSalaryType
conditional generic type into a more flexible type let's use the infer
keyword after the salary
property in the condition followed by a generic type name. Let's name the generic type name as value
and then use that as the truthy value in the condition.
It can be done like this,
// a generic conditional type
type GetSalaryType<T> = T extends { salary: infer value } ? value : never;
// a simple interface called Person
interface Person {
name: string;
salary: string;
}
// get the type of the `salary` property
// from the `Person` interface
type SalaryType = GetSalaryType<Person>; // string
Now let's make 2 more interfaces called Person2
and Person3
where the salary
property is of number
type and an array of strings
type respectively and then pass that to the GetSalaryType
conditional generic type.
It can be done like this,
// a generic conditional type
type GetSalaryType<T> = T extends { salary: infer value } ? value : never;
// an interface where the salary
// property is `string` type
interface Person {
name: string;
salary: string;
}
// an interface where the salary
// property is `number` type
interface Person2 {
name: string;
salary: number;
}
// an interface where the salary
// property is an `array of string` type
interface Person3 {
name: string;
salary: string[];
}
// get the type of the `salary` property
// from the all the above interfaces
type SalaryType = GetSalaryType<Person>; // string
type SalaryType2 = GetSalaryType<Person2>; // number
type SalaryType3 = GetSalaryType<Person3>; // string[]
As you can see that the SalaryType
, SalaryType2
, and the SalaryType3
have different types according to the interfaces passed to the GetSalaryType
conditional generic type.
We have dynamically got the interface
property value type from conditional types successfully in TypeScript. Yay 🥳!
See the above code live in codesandbox.
That's all 😃!
Top comments (0)