[英]Typescript: Input object has subset of keys of an interface
I want to be able to specify that an input object to a function should only contains keys that are present in an existing interface (it does not need to have all the keys). 我希望能够指定函数的输入对象应仅包含现有接口中存在的键(它不需要具有所有键)。
interface Group {
name: string
}
interface Person {
id: number
name: string
email: string
age: number
}
interface AddedProperties {
groups: Group[]
}
function createPerson<D extends object>( // <-- Should convey, D is an object with some keys of Person
personData: D
): D & AddedProperties {
return Object.assign({}, personData, { groups: [] })
}
interface NameAndAge {
name: string
age: number
}
// Valid: Should be valid
const person: NameAndAge = createPerson({ name: "bob", age: 5 })
// Valid: Should be invalid as 'personality' doesn't exist on Person
const person2 = createPerson({ name: "bob", age: 5, personality: "cheerful" })
Is this possible in typescript? 打字稿可能吗?
A simple approach is using Partial<>
: 一种简单的方法是使用
Partial<>
:
function createPerson(
personData: Partial<Person>
): Partial<Person> & AddedProperties {
return { ...personData, groups: [] };
}
Partial
takes a type and makes all of its members optional, thus allowing you to specify any subset of properties of that type. Partial
采用一种类型,并使所有成员都是可选的,因此允许您指定该类型的属性的任何子集。
The downside of this typing is that the returned type has no knowledge of what you put into it: 这种类型的缺点是返回的类型不知道您输入的内容:
createPerson({name: "Bob", age: 5}); // OK
createPerson({name: "Bob", gender: "male"}); // Type error
createPerson({name: "Bob"}).name; // OK
createPerson({name: "Bob"}).age; // OK :-(
If you want to avoid this as well, check out my other answer. 如果您也想避免这种情况,请查看我的其他答案。
OK, I've found the better answer now after some research :-) I'll leave my other answer as well, though. 好的,经过一些研究,我现在找到了更好的答案:-)不过,我也将保留其他答案。 Here's what you can do:
您可以执行以下操作:
function createPerson<D extends keyof Person>(
personData: Pick<Person, D>
): Pick<Person, D> & AdditionalProperties {
return Object.assign({}, personData, {groups: []});
}
This allows personData
to be only a strict subset of Person
, and the return type will be exactly the same structure plus AdditionalProperties
: 这允许
personData
只是Person
personData
集,并且返回类型将具有完全相同的结构以及AdditionalProperties
:
createPerson({name: "Bob", age: 5}); // OK
createPerson({name: "Bob", gender: "male"}); // Type error
createPerson({name: "Bob"}).name; // OK
createPerson({name: "Bob"}).age; // Type error
How does it work? 它是如何工作的? The generic
D extends keyof Person
would, once again, allow adding new fields, which we want to avoid. 泛型
D extends keyof Person
将再次允许添加新字段,我们希望避免这样做。 We cannot handle this in the definition of the generic type argument (since we only have extends
there), but instead limit the actual function argument to 我们不能在泛型类型参数的定义中处理此问题(因为我们仅在那里进行
extends
),而是将实际函数参数限制为
personData: Pick<Person, D>
This restricts the input to only those properties of Person
which appear in D
. 这将输入限制为仅出现在
D
的Person
那些属性。 We use the same type as the return type (intersected with AdditionalProperties
). 我们使用与返回类型相同的类型(与
AdditionalProperties
相交)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.