一、keyof解决访问对象或者数组key,报错不是有效属性的问题
首先,这是一个看似非常正常的代码:
for (const param in params) {
if (params[param]) {
path += `&${param}=${params[param as keyof AlartRulemodel]}`
}
}
嗯?报错了,看看是什么:不要用for in循环,不然引入的运行时库可能太重量级。
OK,那我Object.keys + forEach丝滑小连招:
Object.keys(params).forEach((param) => {
if (params[param]) {
path += `&${param}=${params[param]}`
}
})
嗯?报错了,看看是什么:觉得 param 可能不是 params 有效属性! 好冤啊! 明明是从param出来的!
那那那,我加一个判断?这下ts该不会阻拦我访问params[param]了吧!
Object.keys(params).forEach((param) => {
if (params.hasOwnProperty(param) && params[param]) {
path += `&${param}=${params[param]}`
}
})
嗯?报错了,看看是什么:哦哦,hasOwnProperty 方法是继承自 Object.prototype 的,可能会导致潜在的问题。应该是TS静态分析工具报错。再改改!
fine,我改成in
嗯?报错了,看看是什么:怎么还是觉得 param 不是 params 有效属性!
那类型断言?
Object.keys(params).forEach((param) => {
if (params[param as keyof AlartRulemodel]) {
path += `&${param}=${params[param as keyof AlartRulemodel]}`
}
})
二、进行类型定义
业务场景
如果要将下面一个数组filterOptions的键值依次填到对象form对应的属性中:
使用以下方法:
怎么解决这三个隐式any呢?
- 对于第一个,设置
filreOptions的参数类型,是一个对象数组,我们定义对象的类型即可。它固定有两个属性,直接使用type:
type FilterOption = {
schemaKey: string,
rightModelValue: string
}
这时候可以看出,第二个隐式any由于能自动推断,错误已经消失,当然,也可以为其进行显式指定。
- 对于第三个, 访问数组属性,被指出可能不是有效属性,同一,进行类型断言
type Form = Record<
'alertName' | 'level' | 'ruleGroupId' | 'appName' | 'commander' |
'oncallGroup' | 'createdBy' | 'title' | 'ruleTypeId' | 'isAsuraRule',
string
>
(这时候form的定义也可以用Form进行显示推断了)
const form: Form = reactive({
alertName: '',
level: '',
ruleGroupId: '',
appName: '',
commander: '',
oncallGroup: '',
createdBy: '',
title: '',
ruleTypeId: '',
isAsuraRule: ''
})
最终可执行代码:
const searchAlartRule = async (filterOptions: FilterOption[]) => {
filterOptions.forEach((option) => {
form[option.schemaKey as keyof Form] = option.rightModelValue
})
await getRuleList()
clearForm()
}
Record
Record 的作用是定义一个对象类型,该对象类型包含一组属性,这些属性的名称由 K 类型确定,而属性的值类型由 T 类型确定。
type StudentRecord = Record<string, number>
这样,就定义好了键为string类型,值为numer类型的对象。
const students: StudentRecord = {
"Alice": 18,
"Bob": 19,
"Charlie": 20,
}
当然,也可以用 | 来限制键值:
type Form = Record<
'alertName' | 'level' | 'ruleGroupId' | 'appName' | 'commander' |
'oncallGroup' | 'createdBy' | 'title' | 'ruleTypeId' | 'isAsuraRule',
string
>
Partial 和 ?控制可选
- Partial:每一个属性都是可选的。
// 使用 Partial 类型来定义初始类型
type Form = Partial<{
alertName: string;
level: string;
ruleGroupId: string;
appName: string;
commander: string;
oncallGroup: string;
createdBy: string;
title: string;
ruleTypeId: string;
isAsuraRule: string;
}>;
这里的<>指定的是类型参数。<>还可以用于函数泛型
function identity<T>(arg: T): T {
return arg;
}
- ?:控制单个属性可选。
type Form = {
alertName?: string
level: string
}