当前位置: 首页 > 科技观察

只知道键和值的类型,如何定义TS对象类型?

时间:2023-03-20 13:14:58 科技观察

在学习TS的过程中,你遇到过类似的错误吗?letuser={}user.id="TS001"//属性“id”在类型“{}”上不存在。user.name="Boge"//属性"name"在类型"{}"上不存在。除了什么“大招”,你知道还有多少解法吗?看完这篇文章,你会找到一些答案。这是月薪包括基本工资和月奖金的小王,这是月薪只包括合同工资的小郭。constWang={baseSalary:10000,//底薪monthlyBonus:2000//月奖金};constGuo={contractSalary:15000//contractsalary}这里我们可以实现一个calculateSalary函数来计算他们的工资,计算逻辑实现的很简单。但是问题来了,在TS中如何定义函数参数的类型呢?functioncalculateSalary(salaryObject:???){lettotal=0;for(constnameinsalaryObject){total+=salaryObject[name];}returntotal;}给你3秒的时间考虑一下。你找到答案了吗?一种解决方案是使用索引签名。当我们只知道对象的键和值的类型时,我们可以使用索引签名来定义该对象的类型。这是索引签名的语法:{[key:KeyType]:ValueType}其中Key的类型只能是string、number、symbol或templateliteral类型,value的类型可以是任意类型。interfaceDictionary{[key:boolean]:string;}其中模板文字类型是TypeScript4.1引入的新类型,结合索引签名我们可以定义更强大的类型:interfacePropChangeHandler{[key:`${string}Changed`]:()=>void;}lethandlers:PropChangeHandler={idChanged:()=>{},//OknameChanged:()=>{},//OkageChange:()=>{}//错误};理解了索引签名的语法后,我们就可以轻松定义salaryObject参数的类型:functioncalculateSalary(salaryObject:{[key:string]:number}){lettotal=0;for(constnameinsalaryObject){total+=salaryObject[name];}returntotal;}有时,在定义对象类型时,会出现一些已知和未知的key。这时候我们可以结合索引签名来定义对象的类型:interfaceOptions{[key:string]:string|编号|布尔值;超时:数字;//knownkey}constoptions:Options={timeout:1000,errorMessage:'请求超时!',isSuccess:false};当使用索引签名时,你可能会遇到这些困惑:interfaceNumbersNames{[key:string]:string}constnames:NumbersNames={'1':'one','2':'two','3':'three''};constvalue1=names['1']//Okconstvalue2=names[1]//oktypeN0=keyofNumbersNames//string|number为什么可以通过字符串1和数字1访问到对应的属性值为什么keyofNumbersNames返回的是字符串和数字类型组成的联合类型。这是因为JavaScript在属性访问器中用作键时会隐式地将数字强制转换为字符串,而TypeScript也会执行此转换。除了使用索引签名,我们还可以使用TS自带的工具typeRecordtype来定义calculateSalary函数的参数类型:typeRecord={[PinK]:T;};functioncalculateSalary(salaryObject:Record){lettotal=0;for(constnameinsalaryObject){total+=salaryObject[name];}returntotal;}那么indexsignature和Recordinstrumenttype有什么区别呢?在某些情况下,它们都定义了所需的类型。constuser1:Record={name:"博格"};//好的constuser2:{[key:string]:string}={name:"Boge"};//Okforindex对于签名,key类型只能是string、number、symbol或templateliteral类型。对于Record工具类型,key类型可以是字面量类型,也可以是字面量类型组成的联合类型:typeUser1={[key:"id"]:string;//错误};输入User2={[key:"id"|“名称”]:字符串;//错误};类型User3=Record<"id",string>;//OktypeUser4=Record<"id"|"名称",字符串>;//okconstuser:User4={id:"TS001",name:"阿宝哥",};看完以上内容,你对索引签名和记录工具类型了解了吗?