索引签名类型

时间:2019-07-11 07:48:38

标签: typescript

我在尝试为以下类型编写类型时遇到麻烦:

type Language = 'en' | 'nl';

interface CacheObject {
  [key: string | number | Language]: string;
}

const cache: CacheObject = {};

export const init = (dir: string): Promise<void> =>
  fsPromises.readdir(dir).then(files =>
    files
      .filter(files => files.endsWith('.json'))
      .forEach(async file => {
        cache[file.slice(0, -5)] = await import(`${dir}/${file}`);
      })
  );

export const translate = (lang: Language): any => (key: string) =>
  key.split('.').reduce((acc, val) => acc[val], cache[lang]);

问题如下

const cache: CacheObject
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'CacheObject'.
  No index signature with a parameter of type 'string' was found on type 'CacheObject'.
const cache: CacheObject
Element implicitly has an 'any' type because expression of type 'Language' can't be used to index type 'CacheObject'.
  Property 'en' does not exist on type 'CacheObject'.

有人可以帮我指出正确的方向吗?

1 个答案:

答案 0 :(得分:1)

您忽略了另一个错误:An index signature parameter type must be 'string' or 'number'(TS中可能存在另一个错误,该错误可能会被其他错误抑制,在测试代码时,有时会丢失但出现错误在对代码进行了一些非必要的更改之后。Play with error

如果要使用Languages向类型中添加一些已知元素,则需要在与包含索引签名的类型的交集中使用映射类型:

type CacheObject = {
  [key: string]: string;
  [key: number]: string;
} & Partial<Record<Language, string>>

Play

如果您只有索引签名可以使编译器对使用字符串进行索引编制保持安静,但是该对象只能包含语言,则可以考虑仅对索引表达式进行铸造:

type CacheObject = Partial<Record<Language, string>>
cache[file.slice(0, -5) as Language] = await import(`${dir}/${file}`);

Play