Typescript 如何使这种类型安全?
我有一个方法(UndefineAllLeapProperties),它将undefined设置为所有“叶”属性,以便在访问任何嵌套属性(叶属性的父属性)时不会给出任何未定义的异常 例: 调用UnfineAllLeafProperties(newPerson());应该给Typescript 如何使这种类型安全?,typescript,typescript-typings,typescript-generics,Typescript,Typescript Typings,Typescript Generics,我有一个方法(UndefineAllLeapProperties),它将undefined设置为所有“叶”属性,以便在访问任何嵌套属性(叶属性的父属性)时不会给出任何未定义的异常 例: 调用UnfineAllLeafProperties(newPerson());应该给 { name : undefined, age : undefined, address : { street : undefined, city : undefined
{
name : undefined,
age : undefined,
address : {
street : undefined,
city : undefined
}
}
上述要求的原因是,我只需要填写所需的属性,并在传递给JSON.parse(JSON.stringify(obj))时删除所有属性
问题:当递归调用时,它会抛出一个错误
Argument of type 'T[keyof T]' is not assignable to parameter of type 'object'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'.
Type 'T[string]' is not assignable to type 'object'.
如何在不使用“任何”的情况下解决此问题
export function undefineAllLeafProperties<T extends object>(obj : T) : T {
const keys : Array<keyof T> = Object.keys(obj) as Array<keyof T>;
keys.forEach(key => {
if (obj[key] && typeof obj[key] === "object") {
obj[key] = undefineAllLeafProperties(obj[key]); // recursively call the same function
}
else {
obj[key] = undefined;
}
});
return obj;
}
导出函数UnfineAllLeapProperties(对象:T):T{
常量键:数组=对象。键(obj)作为数组;
keys.forEach(key=>{
if(对象[键]&&typeof对象[键]=“对象”){
obj[key]=UndefineAllLeapProperties(obj[key]);//递归调用同一个函数
}
否则{
obj[key]=未定义;
}
});
返回obj;
}
问题在于此表达式不充当类型保护:
typeof obj[key] === "object"
据我所知,没有“干净”的方法来解决这个问题。在递归调用中添加
将解决此错误:
obj[key] = undefineAllLeafProperties(<any>obj[key])
obj[key]=undefineAllLeafProperties(obj[key])
(即使您强制键入
对象
,您仍然会遇到问题,因为函数随后将返回对象
,该对象不再可分配给obj[key]
)问题在于此表达式不充当类型保护:
typeof obj[key] === "object"
据我所知,没有“干净”的方法来解决这个问题。在递归调用中添加
将解决此错误:
obj[key] = undefineAllLeafProperties(<any>obj[key])
obj[key]=undefineAllLeafProperties(obj[key])
(即使您强制键入对象
,您仍然会遇到问题,因为函数随后将返回对象
,该对象不再可分配给obj[key]
)解决方案
下面的代码没有错误,返回类型安全的对象。我所做的改进是:
记录
在对象
上,记录更具限制性,允许重新分配密钥Undefined
type,因此TypeScript知道返回类型中的所有值都将是未定义的作为T[keyof T]
,TypeScript不知道我们分配给什么键,因为我们使用泛型。这里的解决方案是将它转换为T[keyof T]
,让TS放心,我们知道我们在做什么(我希望有更好的解决方案,但我找不到)接口人{
年龄:人数;
姓名:{
第一:字符串;
最后:字符串;
};
}
警察:人={
年龄:9岁,
姓名:{
第一:“第一”,
最后:“最后”
}
};
类型Undefined={[P in keyof T]:Undefined};
导出函数UnfineAllLeafProperties(
对象:T
):未定义{
Object.keys(obj.forEach)(key:keyof T)=>{
if(对象[键]&&typeof对象[键]=“对象”){
obj[key]=未定义的叶子属性(obj[key])作为T[keyof T];
}否则{
obj[key]=未定义为T[keyof T];
}
});
返回obj;
}
常数pu=未定义的叶属性(p);
控制台日志(pu);
沙箱:
可选链
在你的问题中,你提到:
…以便在访问任何嵌套属性(叶属性的父属性)时不会出现任何未定义的异常
JavaScript和TypeScript添加了一个功能来解决这个问题,称为可选链接
let street=person?address?street;
在本例中,如果person
或address
未定义,则不会引发异常,只将未定义分配给street
如果您使用的是TypeScript>=3.7,则可以使用此语法。或者,您可以将Babel与
在此处了解更多信息:解决方案
下面的代码没有错误,返回类型安全的对象。我所做的改进是:
记录
在对象
上,记录更具限制性,允许重新分配密钥Undefined
type,因此TypeScript知道返回类型中的所有值都将是未定义的作为T[keyof T]
,TypeScript不知道我们分配给什么键,因为我们使用泛型。这里的解决方案是将它转换为T[keyof T]
,让TS放心,我们知道我们在做什么(我希望有更好的解决方案,但我找不到)接口人{
年龄:人数;
姓名:{
第一:字符串;
最后:字符串;
};
}
警察:人={
年龄:9岁,
姓名:{
第一:“第一”,
最后:“最后”
}
};
类型Undefined={[P in keyof T]:Undefined};
导出函数UnfineAllLeafProperties(
对象:T
):未定义{
Object.keys(obj.forEach)(key:keyof T)=>{
if(对象[键]&&typeof对象[键]=“对象”){
obj[key]=未定义的叶子属性(obj[key])作为T[keyof T];
}否则{
obj[key]=未定义为T[keyof T];
}
});
返回obj;
}
常数pu=未定义的叶属性(p);
控制台日志(pu);
沙箱:
可选链
在你的问题中,你提到:
…以便在访问任何嵌套属性(叶属性的父属性)时不会出现任何未定义的异常
JavaScript和TypeScript添加了一个功能来解决这个问题,称为可选链接
let street=person?address?street;
在本例中,如果person
或address
未定义,则不会引发异常,只将未定义分配给street
如果您使用的是TypeScript>=3.7,则可以使用此语法。或者,您可以将Babel与
在此了解更多信息:您是否尝试创建地址类并将其用作地址类型