我正在尝试创建一个动态函数,检查某个元素是否满足某些标准作为此问题的扩展。
我目前的问题是key
字符串变得不可用作为密钥,因为没有签名。如何使key
对所有传入类型都是动态的?
type TypeA = { id: string; equipment: string; weight: string }
type TypeB = { id: string; equipment: string; material: string }
type TypeC = { id: string; equipment: string; width: string }
type TypeD = { id: string; equipment: string; old: string }
type TypeE = { id: string; equipment: string; recent: string }
type TypeF = { id: string; equipment: string; broken: string }
type AllTypes = (TypeA | TypeB | TypeC| TypeD | TypeE | TypeF )[]
const items : AllTypes = [{ id: '11245', equipment: 'hammer', recent: 'yes' }, { id: '11335', equipment: 'screwdriver', material: 'metal' }]
const typeExclude = (key: string, el: TypeA | TypeB | TypeC| TypeD | TypeE | TypeF) => {
return key in el ? el[key as any /*the current type at hand*/] : undefined;
};
const arr = items.map(el => typeExclude('material', el) ? 'valid':'invalid')
console.log(arr)
我认为您面临的问题是由于in
操作符类型缩小适用于字符串字面量,但不适用于变量。
解决方案是实现您自己的类型保护,它断言key
变量的值是所讨论对象的实际键。
type TypeA = { id: string; equipment: string; weight: string }
type TypeB = { id: string; equipment: string; material: string }
type TypeC = { id: string; equipment: string; width: string }
type TypeD = { id: string; equipment: string; old: string }
type TypeE = { id: string; equipment: string; recent: string }
type TypeF = { id: string; equipment: string; broken: string }
type Type = TypeA | TypeB | TypeC | TypeD | TypeE | TypeF;
type Key<U> = U extends U ? keyof U : never;
const items: Type[] = [
{ id: '11245', equipment: 'hammer', recent: 'yes' },
{ id: '11335', equipment: 'screwdriver', material: 'metal' }
];
const hasKey =
<T extends object>(o: T, key: PropertyKey): key is keyof T => key in o;
const typeExclude =
(key: Key<Type>, el: Type) => hasKey(el, key) ? el[key] : undefined
const arr = items.map(el => typeExclude('material', el) ? 'valid' : 'invalid');
console.log(arr);
<一口>操场链接一口>
此外,我还创建了一个分布式条件类型Key<U>
,它创建了属于U
联合的所有类型的键的联合。这限制了typeExclude()
函数的key参数只能接受已知的键。
我看到这个问题已经解决了,但我认为下面的代码稍微干净一点,更少的代码与我尝试使用接口。
interface IType {
id: string;
equipment: string;
weight?: string;
material?: string;
width?: string;
old?: string;
recent?: string;
broken?: string;
}
const items: IType[] = [
{ id: "11245", equipment: "hammer", recent: "yes" },
{ id: "11335", equipment: "screwdriver", material: "metal" },
];
const typeExclude = <T extends keyof IType>(key: T, obj: IType) => {
return key in obj ? obj[key] : undefined;
};
const arr = items.map((el) =>
typeExclude("material", el) ? "valid" : "invalid"
);
console.log(arr); // ['invalid', 'valid']