潍坊网站建设自助建站平台,借贷网站建设方案,男女做那个什么的视频网站,网站前置审批类型目录 1#xff0c;什么是索引签名1#xff0c;js 中使用对象的属性2#xff0c;ts 中的索引签名3#xff0c;扩展索引签名定义的类型 2#xff0c;与 Record 对比3#xff0c;遇到的问题1#xff0c;索引 key 的类型问题#xff0c;keyof2#xff0c;索引 key 的类型问… 目录 1什么是索引签名1js 中使用对象的属性2ts 中的索引签名3扩展索引签名定义的类型 2与 Record 对比3遇到的问题1索引 key 的类型问题keyof2索引 key 的类型问题2受具体定义的影响 1什么是索引签名
1js 中使用对象的属性
在 js 中访问对象的 key
let user {name: 下雪天的夏风,19: 19value,
};console.log(user.name);
console.log(user[19]);
user.age 18如果key 是对象会默认执行它的 toString() 方法。
let user {name: 下雪天的夏风,
};
const obj {toString() {console.log(be string);return _obj;},
};user[obj] 关注一波;
console.log(user);
// be string
// { name: 下雪天的夏风, _obj: 关注一波 }其他的类型来看下结果
let user {};const obj1 {toString() {console.log(be string);return _obj;},
};
const obj2 {};
function foo() {}
const sym Symbol();user[obj1] obj1 的 value;
user[obj2] obj2 的 value;
user[foo] foo 的 value;
user[sym] sym 的 value;
console.log(user); // { name: 下雪天的夏风, _obj: 关注一波 }/*
be string
{_obj: obj1 的 value,[object Object]: obj2 的 value,function foo() {}: foo 的 value,[Symbol()]: sym 的 value
}
*/可以看到对象默认的 toString() 方法执行结果比较特殊。 2ts 中的索引签名
可以简单的理解key 就是索引。
基于在 js 中对象和函数等作为索引产生的特殊行为ts 做了进一步的约束。 索引类型只能是string | number | symbol而value 可以是任意类型。
其中string 也可以是模板字面量
interface HandleEvents {[key: ${string}Changed]: () void;
}对象如果想作为索引必须显示的调用.toString() 方法
let user: any {};const obj1 {toString() {return _obj1;},
};// Type { toString(): string; } cannot be used as an index type.ts(2538)
user[obj1] obj1 的 value;
user[obj1.toString()] ok;索引签名就是在约束了索引key类型的基础上统一定义了对象的 key 和 value 的类型。
换句话说索引签名可以在只知道key和value 的类型下来统一定义对象的类型。 规定当声明一个索引签名后所有成员都必须符合索引签名 举例
interface Sign1 {// key 只是占位符随便什么单词都可以[key: string]: string;
}type Sign2 {[index: number]: string | number;
};const foo: {[aaa: string]: { message: string }; // value 只能是1个对象并且只有1个属性 message
} {};3扩展索引签名定义的类型
可同时指定已确定的类型
// 必须包含 x 属性
interface Sign1 {[key: string]: number;x: number;
}interface Sign2 {[key: string]: number;y: string; // Error: 属性 y 的类型只能是number.ts(2411)
}多个索引签名 在多个索引签名存在时string 类型的索引最严格书写时应该包含所有的 value 类型假设为 All。 其他类型的索引对应的 value 类型只能是 All 的子级。 interface Sign3 {[key: string]: string | number | boolean; // 必须包括所用成员类型[index: symbol]: string;[index2: number]: number;
}扩展
即便使用多个索引签名也有覆盖不到的情况。
比如定义的对象中有一个liststring[] 字段其他字段都不是string[] 类型。如果按照下面的写法任何字段都可以是string[] 类型。
interface Sign4 {[key: string]: string | number | string[]; // 必须包括所用成员类型
}我们可以用索引签名联合类型。
type Sign4 {[key: string]: string | number;
} | { list: string[] }2与 Record 对比
先看下 Record 的定义
// node_modules\typescript\lib\lib.es5.d.ts
type RecordK extends keyof any, T {[P in K]: T;
};鼠标放上去之后会发现其实 key 和value的类型的规则和索引签名的一致也是string | number | symbol而value 可以是任意类型。
所以二者并没有多大的区别只是使用上略有不同而已。目前只发现的一个区别
Record 的 key 可以为具体的类型一般用于创建具有特定键值对的对象类型。
type Type1 Recorda | b | c, string3遇到的问题
1索引 key 的类型问题keyof
type Sign {[key: string]: boolean;
}
// string | number
type keys keyof Signconst obj: Sign {};
obj[2] 123; // ok
obj[3] 123;原因是当数字作为 key 时js 会隐式地将数字强制转换为字符串ts 也会执行这种转换。
2索引 key 的类型问题2受具体定义的影响
这是我的提问
script setup langts
interface NumberDictionary {[index: string]: string;
}const formInfo: NumberDictionary {name: john,want: eat,
};Object.entries(formInfo).forEach(([key, value]) {console.log(key, value);
});
/script
templateforminput v-for(value, key) in formInfo :namekey :valuevalue :keykey typetext //form
/template可以看到2个地方 key 的类型不一致 原因
Object.entries 的类型声明
// node_modules\typescript\lib\lib.es2017.object.d.ts
entriesT(o: { [s: string]: T } | ArrayLikeT): [string, T][];可以看到接受的就是 string 类型相当于在 forEach 使用时key 已经被断言为 string 类型了。
v-for 的类型声明
// node_modules\vue\runtime-core\dist\runtime-core.d.ts 第 1602 行
/*** v-for object*/
export declare function renderListT(source: T, renderItem: K extends keyof T(value: T[K], key: K, index: number) VNodeChild)
: VNodeChild[];可以看到 K extends keyof T很熟悉这就是上面遇到的第1个问题。 对上面这个例子来说v-for 中 key 的类型就是 string | number。
知道原因了解决方法就有了用Record 即可
interface NumberDictionary {[index: string]: string;
}
// ↓↓
type NumberDictionary Recordstring, string以上。 参考
索引签名-参考1
索引签名-参考2
索引签名-参考3