In certain cases I'd like to widen the type of an object which is casted literally (using "as const"), so it's properties will be inferred as strings or numbers, and not literally.
Imagine I have the following type
const obj = [
{
type:"student",
name:"Yossi"
},
{
type: "Teacher",
name: "Lili"
}
] as const
type Person = typeof obj [number]
I'd like the type of obj to be inferred literally, but Person to be Wider, so it's type and name are strings. Is there a generic which can allow the following:
type Person = Widen<typeof obj [number]>
Assigning Generic ParametersBy passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
'T' is going to be a type declared at run-time instead of compile time. The T variable could be any non-declared variable (I couldn't find a reference, but I would assume any valid set of characters that could be used for a variable names).
TypeScript - Generic Interface The above IProcessor is a generic interface because we used type variable <T> . The IProcessor interface includes the generic field result and the generic method process() that accepts two generic type parameters and returns a generic type. As you learned, you can use interface as type.
Generics allow creating 'type variables' which can be used to create classes, functions & type aliases that don't need to explicitly define the types that they use. Generics makes it easier to write reusable code.
Interesting case. We can try to create such utility by mapped types. Consider:
// it transforms our specific types into primitive origins
type ToPrimitive<T> =
T extends string ? string
: T extends number ? number
: T extends boolean ? boolean
: T;
// mapped types which will preserve keys with more wide value types
type Widen<O> = {
[K in keyof O]: ToPrimitive<O[K]>
}
// using
type Person = Widen<typeof obj[number]>
const a: Person = {
name: 'name', // string
type: 'type' // string
}
We can extend ToPrimitive
to also consider other types like object, array by adding additional conditions.
As I see your obj
type of elements in terms or primitive types is one - {name: string, type: string}
. Then we can just create a type from a first element by:
type Person = Widen<typeof obj[0]>;
// and this nicely evaluates to:
type Person = {
readonly type: string;
readonly name: string;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With