参数中基于泛型模型的返回类型

时间:2021-03-15 17:38:44

标签: typescript typescript-typings typescript-generics

function getModelDetails<T>(model: Partial<Record<keyof T, unknown>>): Record<keyof typeof model, unknown> {
  return (model as unknown) as Record<keyof typeof model, unknown>;
}
interface Person {
  firstName: string;
  lastName: string;
  age: number;
}

// person is assigned with an object with all the Person properties instead of only "firstName" and "lastName"
const person = getModelDetails<Person>({ firstName: 'jon', lastName: 'smith' });

无论如何都要返回传递给泛型函数的任何东西的类型,而不是仅仅返回类型的所有属性?

我也不想指定要返回的属性,我基本上想找到一种方法,根据传递给函数的属性来设置返回类型。

我什至不确定这是否可能,但在此先感谢;)

需要

// person only with {firstName:"...", lastName: "..."}
const person = getModelDetails<Person>({ firstName: 'jon', lastName: 'smith' });

1 个答案:

答案 0 :(得分:2)

这里涉及两个通用值:模型的类型和我们传递的属性子集。您已经说过要指定第一个泛型,但允许推断第二个。这不是您可以使用单个功能完成的事情。您需要使用柯里化,也就是“双重功能”。

function getModelDetails<Model>() {
    return function <Keys extends keyof Model>(model: Pick<Model, Keys>): Pick<Model, Keys> {
        return model;
    }
}

您可以使用返回类型 [K in Keys]: Model[K] 而不是 Pick<Model, Keys>。它们的意思是一样的,但如果你手动写出来,那么当你将鼠标悬停在变量上时,你会得到 { firstName: string; lastName: string; } 而不是 Pick<Person, "firstName" | "lastName">。看你喜欢哪个。

要使用此函数,您需要一组额外的括号 () 来调用第一个将 Model 设置为 Person 的函数。

// person has type: Pick<Person, "firstName" | "lastName">
const person = getModelDetails<Person>()({ firstName: 'jon', lastName: 'smith' });

// error if adding unsupported property
// TS2345: Object literal may only specify known properties, and 'somethingElse' does not exist in type 'Pick<Person, keyof Person>'
const person2 = getModelDetails<Person>()({firstName: 'jon', lastName: 'smith', somethingElse: '' });

// if you don't set the first generic then you get type Pick<unknown, never> because we don't have any default value
const person3 = getModelDetails()({ firstName: 'jon', lastName: 'smith' });

Typescript Playground Link