简体   繁体   English

打字稿:输入对象具有接口键的子集

[英]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 . 这将输入限制为仅出现在DPerson那些属性。 We use the same type as the return type (intersected with AdditionalProperties ). 我们使用与返回类型相同的类型(与AdditionalProperties相交)。


You can see it in action here : 您可以在这里查看它的运行情况:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Typescript 接口 object 按键 - Typescript interface object keys Typescript:断言未知输入的类型为 Pick<concretetype, subset of keys concretetype> 对于指定的键</concretetype,> - Typescript: Assert unknown input has type Pick<ConcreteType, subset of keys of ConcreteType> for specified keys 将一个object转换为typescript中key较少的接口 - Convert an object to an interface with less keys in typescript 从具有键和值的界面创建 object - typescript - Create an object from interface with keys and values - typescript 具有扩展对象的动态键的Typescript接口 - Typescript interface with dynamic keys extending Object Typescript 接口结合 object 属性上的 map 的键 - Typescript Interface combined with keys of map on object property TypeScript:如何创建一个类型或接口,它是一个具有n个键之一或是字符串的对象? - TypeScript: How to create a type or interface that is an object that has one of n keys or is a string? 如何仅收集具有 object 类型的键,其中某些特定键作为 Typescript 接口中的值? - How to only collect keys in a type that has an object with some specific key as a value in Typescript interface? 具有嵌套对象的对象数组的打字稿接口 - Typescript interface for Array of object that has nested object Typescript - 如何从 object 获取属性子集到基于接口的变量中 - Typescript - How to get a subset of properties from an object into a variable based on an interface
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM