任意类型定义给出:“boolean"类型的属性“x"不可分配给字符串索引类型“string" [英] arbitrary type definition gives: Property 'x' of type 'boolean' is not assignable to string index type 'string'

查看:44
本文介绍了任意类型定义给出:“boolean"类型的属性“x"不可分配给字符串索引类型“string"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎这个 是相关的,但我不明白.

这是我想要的示例:

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)

很高兴得到一些指导.

<小时>

@埃弗特:

让我的对象:{[键:字符串]:字符串|布尔值,btnWrap:布尔值}myObj = {'arr0': 'val0', 'arr1': {'arr1': 'val1', 'btnWrap': false}};

<块引用>

输入'{'arr1':字符串;'btnWrap':布尔值;}' 不能分配给类型 'string |布尔'.输入'{'arr1':字符串;'btnWrap':布尔值;}' 不可分配给类型 'true'.ts(2322)

解决方案

错误信息是因为 btnWrap 类型 boolean字符串索引 类型 string.类型 {[key: string]: string, btnWrap: boolean}} 试图说明每个属性都有一个字符串值 and 表示 btnWrap 有一个布尔值.它们不可能都为真,因此编译器会警告您.

<小时>

没有一个具体的类型 MyObj 代表您所描述的约束.但是您可以创建一个 generic 类型,它采用键字面量 K 的并集并产生一个类型 MyObj:

type MyObj={ [P in K]: 字符串 |(Record<P, string> & { btnWrap: boolean }) };

类型 MyObj 是一个 映射类型,其中键为 P 的每个属性要么具有值类型 string,要么具有 intersection{btnWrap: boolean}Record.后一种类型本身就是一个映射类型(在标准库中定义) 键P 和属性string.所以 MyObject<K> 的每个属性必须看起来像 someKey: stringsomeKey: {btnWrap: boolean, someKey: string}.

同样,要描述 myObj 的类型,而不是像 let myObj: MyObj = ... 这样简单的东西,你必须像 letmyObj: MyObj<"key1"|"key2"|"key3">= ... 在其中指定通用参数.为了避免您必须自己执行此操作,您可以使用通用辅助函数来帮助 推断给定一个对象的K的类型,像这样:

const asMyObj = >(myObj: T) =>我的对象;

现在让我们试试:

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

那些工作得很好.现在让我们看看如果您违反约束会出现什么问题:

let badMyObj1 = asMyObj({ key1: 1 });//错误,数字不好让 badMyObj2 = asMyObj({ key1: "val1", key2: { key2: "val2" } });//错误,缺少 btnWrap让 badMyObj3 = asMyObj({ key1: "val1", key2: { btnWrap: true } });//错误,缺少 key2 里面的值让 badMyObj4 = asMyObj({ key1: "val1", key2: { key3: "val3", btnWrap: true } });//错误,key3 不是预期的内部值

那些错误可能正是您想要看到的,对吗?

<小时>

好的,希望有帮助.这是一个 Playground 链接到上述代码.祝你好运!

it seems THIS is related, yet I dont understand.

here is an example of what I want:

myObj should accept the following settings:

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

So I came up with the following type definition:

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

Property 'btnWrap' of type 'boolean' is not assignable to string index type 'string'.ts(2411)

(I dont understand the above error message.)

Please note:

  • key1, 2, 3 stand for ARBITRARY key-names.
  • in 'key2': {'key2': 'val2', 'btnWrap': true} please note it should be the SAME arbitrary key-name. (key2 for eg)

Im happy for some guidance.


@Evert:

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

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

Type '{ 'arr1': string; 'btnWrap': boolean; }' is not assignable to type 'string | boolean'. Type '{ 'arr1': string; 'btnWrap': boolean; }' is not assignable to type 'true'.ts(2322)

解决方案

The error message is because the btnWrap type boolean doesn't match the string index type string. The type {[key: string]: string, btnWrap: boolean}} is trying to say that every property has a string value and that btnWrap has a boolean value. They can't both be true, so the compiler warns you.


There isn't a single concrete type MyObj that represents the constraint as you described it. But you can create a generic type which takes the union of key literals K and produces a type MyObj<K>:

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

The type MyObj<K> is a mapped type where each property with key P either has value type string, or the intersection of {btnWrap: boolean} with Record<P, string>. The latter type is itself a mapped type (defined in the standard library) with keys P and properties string. So each property of MyObject<K> must either look like someKey: string or someKey: {btnWrap: boolean, someKey: string}.

Again, to describe the type of myObj, instead of something simple like let myObj: MyObj = ..., you have to do something like let myObj: MyObj<"key1"|"key2"|"key3"> = ... where you specify the generic parameters. To prevent you from having to do this yourself, you can use a generic helper function to help infer the type of K given an object, like this:

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

Now let's try it:

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

Those work just fine. Now let's see what goes wrong if you violate your constraint:

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

Those errors are probably what you want to see, right?


Okay, hope that helps. Here's a Playground link to the above code. Good luck!

这篇关于任意类型定义给出:“boolean"类型的属性“x"不可分配给字符串索引类型“string"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆