我有一个超类型的对象compactUser
,并且我想以类型安全的方式基于对象detailedUser
创建一个子类型的对象compactUser
。
我有一个可行的解决方案,在下面的代码中detailedUser1
,但是我想针对更复杂的场景提供更灵活的方法(沿着detailedUser2
行)。
(对不起,这看起来是一个基本的打字稿问题,我确实在寻找解决方案,但最终在这里提出了问题。)
(code)
interface CompactUser {
id: number
}
interface DetailedUser {
id: number
name: string
sex: string
}
const compactUser: CompactUser = {id: 1}
const detailedUser1: DetailedUser = {
...compactUser,
name: 'nume',
sex: 'm',
}
// I don't like this; it's more flexible, but error prone
const detailedUser2 = compactUser as DetailedUser
// ups, I set `sex`, but forgot about `name`
detailedUser2.sex = Math.random() > 0.5 ? 'f' : 'm'
// not ok - I access `name` and there's no typescript error
console.log(detailedUser2.name)
答案 0 :(得分:0)
我有一个可行的解决方案,在下面的代码中
detailedUser1
您的操作方式就是您的操作方式,如您的示例中那样使用扩展符号:
const detailedUser1: DetailedUser = {
...compactUser,
name: 'nume',
sex: 'm',
};
...或Object.assign
:
const detailedUser1: DetailedUser = Object.assign(
{},
compactUser,
{
name: 'nume',
sex: 'm',
}
};
在这些中,我想说传播是最清晰,最常见的。请注意,这两个属性均保留compactUser
的 all 属性,但是在您的情况下compactUser
仅具有适合DetailedUser
的属性,因此很好。
如果存在更复杂的场景,您可能希望将它们放在可重用的函数中,但它们在本质上将是相似的。
我想更灵活一些(沿
detailedUser2
行)...
您的detailsUser2
根本不会做任何事情来使对象适合该类型,它只是向TypeScript断言它是必需的类型。从那时起,该对象与它的类型信息不同步,因为它没有name
和sex
,但是它的类型表明它确实有:
console.log("sex" in detailedUser2); // false, but the type says it has to be true
这就是为什么您必须做与detailedUser1
一样的事情。
如果要使用更新的类型信息重用同一对象,可以执行以下操作:
const detailedUser2: DetailedUser = Object.assign(compactUser, {name: "x", sex: "f"});
例如,提供缺少的属性。这样就可以更新compactUser
。 (同样,如果compactUser
的属性DetailedUser
不存在,即使类型表明它们不存在,它们也会存在;但是,在您的示例中情况并非如此。)>
detailedUser1
和上面的Object.assign
的优点之一是,如果您忘记了属性,TypeScript会告诉您:
const detailedUser2: DetailedUser = {...compactUser, {name: "x"});
// ^^^^^^^^^^^^^-- Property 'sex' is missing in type 'CompactUser & { name: string; }' but required in type 'DetailedUser'.
和
const detailedUser2: DetailedUser = Object.assign(compactUser, {name: "x"});
// ^^^^^^^^^^^^^-- Property 'sex' is missing in type 'CompactUser & { name: string; }' but required in type 'DetailedUser'.