省略对象的属性注释

时间:2019-09-26 17:14:37

标签: typescript

我正在尝试创建语言环境字符串对象:

const strings = {
  hello: {
    en: 'hello',
    pl: 'hej'
  },
  bye: {
    en: 'bye',
    pl: 'pa'
  }
}

如果我输入strings.并向我显示hellobye可用,则此方法有效。但是,这并没有强制执行任何操作,某些属性可能会丢失enpl或什至没有其他属性。为了更具体,我声明了一个枚举并键入了对象:

enum Language {
  en = 'en',
  pl = 'pl'
}

type Strings = { [k: string]: { [lang in Language]: string } }

const strings: Strings = {
  // ...same as before
}

太好了!现在,我的strings属性已正确键入。但是,等等,现在由于[k: string],我失去了在属性上的键入。根据ts,strings.dontExist现在可以了(可以理解)。

所以我的问题是我如何实现推断的属性(就像第一个示例中一样),但又要获得我明确设置的强类型属性({ [lang in Language]: string })?

[使用打字稿3.6.2]

2 个答案:

答案 0 :(得分:1)

虽然我认为如果您改变结构(例如将enpl放在顶层,则输入起来会容易得多),但我认为您必须创建对象,然后将键的类型推断为新对象,如下所示:

enum Language {
  en = 'en',
  pl = 'pl'
}

type Translation =  { [lang in Language]: string } 

const strings  = {
  hello: {
    en: 'hello',
    pl: 'hej'
  },
  bye: {
    en: 'bye',
    pl: 'pa'

  }
}

type TranslationGroup =  keyof typeof strings;

const typed: Record<TranslationGroup, Translation> = strings

typed.foo //error

答案 1 :(得分:1)

我可能只是将Strings的键K设为通用,像这样:

type Strings<K extends string> = { [P in K]: { [L in Language]: string } };

然后,您可以使用一个小的辅助函数从对象文字中推断出K,而不必强迫您重新输入它:

const asStrings = <K extends string>(s: Strings<K>) => s;

它是这样的:

const strings = asStrings({
  hello: {
    en: "hello",
    pl: "hej"
  },
  bye: {
    en: "bye",
    pl: "pa"
  }
}); // Strings<"hello" | "bye">

如果您省略一种语言,则应该会出错。希望有帮助!

Link to code