keyof doesn't return correct type when used with Record

281 views Asked by At

I have a list of countries in an object

const CountryCodes = {
  DE: {
    countryCode: 'DE',
    countryName: 'Deutschland',
    phoneCode: 49,
  },
  US: {
    countryCode: 'US',
    countryName: 'United States',
    phoneCode: 1,
  },
  ...
}

And an interface for it's content

type CountryCode = {
  countryCode: string;
  countryName: string;
  phoneCode: number;
};

If I don't give a type to CountryCodes and get it's keys with keyof typeof CountryCodes it returns the correct result which is 'DE' | 'US' ...

But if i don't give a type there can be errors in this object, someone can add / substract an element. So i want to strictly type CountryCodes object with CountryCode type.

const CountryCodes: Record<string, CountryCode> = { ...

But with this type, result of the keyof typeof CountryCodes is now just string as stated in Record<string, CountryCode>

Is there a way where I can strictly type this object and still get the keys of countries with keyof?

2

There are 2 answers

1
md2perpe On BEST ANSWER

Here's one way, where the data is first put in a temporary variable which is then assigned to the correct variable and "casted" to the wanted type:

const _CountryCodes = {
  DE: {
    countryCode: 'DE',
    countryName: 'Deutschland',
    phoneCode: 49,
  },
  US: {
    countryCode: 'US',
    countryName: 'United States',
    phoneCode: 1,
  },
}

const CountryCodes: Record<keyof typeof _CountryCodes, CountryCode> = _CountryCodes;
1
md2perpe On

You can hardcode the valid keys:

type CountryKey = 'DE' | 'US';

const CountryCodes: Record<CountryKey, CountryCode> = {