任意类型定义给出:类型“ boolean”的属性“ x”不可分配给字符串索引类型“ string”

时间:2019-03-19 15:24:11

标签: typescript typescript-typings

似乎THIS相关,但我不明白。

这是我想要的例子:

myObj应该接受以下设置:

myObj = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'};
myObj = {'key1': 'val1', 'key2': {'key2': 'val2', 'btnWrap': true}, 'key3': 'val3'};

所以我想出了以下类型定义:

let myObj: {[key: string]: string | {[key: string]: string, btnWrap: boolean}}
  

类型'boolean'的属性'btnWrap'无法分配给字符串索引类型'string'.ts(2411)

(我不理解上面的错误消息。)

请注意:

  • key1、2、3代表任意键名。
  • 'key2': {'key2': 'val2', 'btnWrap': true}中,请注意它应该是相同的任意键名。 (例如,key2)

很高兴获得一些指导。


@Evert:

let myObj: {
  [key: string]: string | boolean,
  btnWrap: boolean
}

myObj = {'arr0': 'val0', 'arr1': {'arr1': 'val1', 'btnWrap': false}};
  

输入'{'arr1':string; 'btnWrap':布尔值; }”不可分配给“ string |布尔”。     输入'{'arr1':string; 'btnWrap':布尔值; }”不能分配为“ true”类型。ts(2322)

2 个答案:

答案 0 :(得分:3)

错误消息是因为btnWrap类型的booleanstring index类型的string不匹配。类型{[key: string]: string, btnWrap: boolean}}试图说每个属性都有一个字符串值,而btnWrap有一个布尔值。它们都不是真的,所以编译器会警告您。


没有一个具体的类型MyObj代表您所描述的约束。但是您可以创建一个generic类型,该类型采用键文字K的并集,并产生一个类型MyObj<K>

type MyObj<K extends keyof any> = 
  { [P in K]: string | (Record<P, string> & { btnWrap: boolean }) };

类型MyObj<K>mapped type,其中每个键为P的属性要么具有值类型string,要么具有值{btnWrap: boolean}的{​​{3}}与Record<P, string>。后一种类型本身是具有键P和属性string的映射类型(intersection)。因此,MyObject<K>的每个属性必须类似于someKey: stringsomeKey: {btnWrap: boolean, someKey: string}

同样,为了描述myObj的类型,您必须执行let myObj: MyObj = ...之类的操作来指定通用参数,而不是像let myObj: MyObj<"key1"|"key2"|"key3"> = ...之类的简单操作。为避免您必须自己执行此操作,可以使用通用帮助函数来帮助defined in the standard library给定对象的K类型,例如:

const asMyObj = <T extends MyObj<keyof T>>(myObj: T) => myObj;

现在让我们尝试一下:

let myObj1 = asMyObj({ key1: 'val1', key2: 'val2', key3: 'val3' });
let myObj2 = asMyObj({ key1: 'val1', key2: { key2: 'val2', btnWrap: true }, key3: 'val3' });

这些工作正常。现在,让我们看看如果您违反约束会出什么问题:

let badMyObj1 = asMyObj({ key1: 1 }); 
// error, number is bad

let badMyObj2 = asMyObj({ key1: "val1", key2: { key2: "val2" } }); 
// error, missing btnWrap

let badMyObj3 = asMyObj({ key1: "val1", key2: { btnWrap: true } }); 
// error, missing key2 inside value

let badMyObj4 = asMyObj({ key1: "val1", key2: { key3: "val3", btnWrap: true } }); 
// error, key3 not expected inside value

这些错误可能就是您想要看到的,对吧?


好的,希望能有所帮助。这是上述代码的infer。祝你好运!

答案 1 :(得分:1)

您键入的内容定义如下:

  • 所有属性应为字符串或某些内部类型(InnerObj
  • InnerObj属性应为字符串或布尔值

这是定义它的方法:

type InnerObj = {
  [key: string]: string | boolean;
  btnWrap: boolean;
};

type Obj = {
  [key: string]: string | InnerObj;
}

const myObj1: Obj = { key1: 'val1', key2: 'val2', key3: 'val3' };
const myObj2: Obj = { key1: 'val1', key2: { key2: 'val2', btnWrap: true }, key3: 'val3' };