Having an object like
const translations = {
say_hello: 'hello {{name}}',
};
I'd like to extract the exact type of the object, like
type Translations = {
say_hello: 'hello {{name}}',
}
So far I'm playing around something like
type GetExactType<T> = {[K in keyof T]-?: T[K]};
but it doesn't work as expected, because
GetExactType<typeof translations>;
resolves to
{
say_hello: string,
}
Any ideas?
CodePudding user response:
You could use as const
but that results in readonly
on everything, which might not be desirable.
Instead, you could have a function to narrow it for you:
type Narrow<T> =
| (T extends infer U ? U : never)
| Extract<T, number | string | boolean | bigint | symbol | null | undefined | []>
| ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> });
function narrow<T>(t: Narrow<T>): T {
return t as T;
}
And then when you use it, it'll infer the types for you:
const translations = narrow({
say_hello: 'hello {{name}}',
});
type T = typeof translations;
// ^? { say_hello: 'hello {{name}}'; }
Note that it is impossible to retrieve the original type after you define it like this:
const translations = {
say_hello: 'hello {{name}}',
};
so some sort of direct operation on the value before it is assigned is required.
CodePudding user response:
You have to tell TypeScript that the say_hello
property's type is 'hello {{name}}'
, not string
. There are at least a couple of ways to do that:
Via
as const
, saying that the object won't change:const translations = { say_hello: 'hello {{name}}', } as const; //^^^^^^^^ type Translations = typeof translations;
Explicitly:
const translations = { say_hello: 'hello {{name}}' as 'hello {{name}}', // −−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^ }; type Translations = typeof translations;
(but...ewww...)
or
const translations: { say_hello: 'hello {{name}}' } = { say_hello: 'hello {{name}}', }; type Translations = typeof translations; // (But if you were going to do that, you'd just want to write the type // alias manually and then apply it to the `translations` constant, rather // than doing it this way around.)
I use the as const
for things like translation strings all the time.