在仍能推断类型的同时,能否在此函数中获得TypeScript自动完成功能?

时间:2018-12-20 10:49:17

标签: typescript

我正在编写一组工厂函数,每个工厂函数将返回更大的整体对象的一部分。由于它是一种复杂的类型,因此我希望能够使用智能感知来帮助我编写这些功能。

我不知道使用哪种返回类型来注释函数,以确保获得智能/自动完成功能。到目前为止,我已经尝试了三件事。对于这些示例,您可以假设FooType被定义为:

interface FooType {
    prop1: boolean;
    prop2: boolean;
    ...
}

选项一

我可以使用类型推断来自动确定函数的类型,但是然后我没有任何类型推断。

function PartialFooMaker1() {
   return {
        prop1: true,
        // I want autocomplete in here
   }
}
function PartialFooMaker2() {
   return {
        prop2: true,
        // I also want autocomplete in here
   }
}

export const Foo: FooType = Object.assign({}, PartialFooMaker1(),PartialFooMaker2());

选择二

我可以将完整类型指定为函数返回类型,但是如果我省略一些属性,那将(正确)触发编译错误。

function PartialFooMaker1(): FooType {
   return {
        prop1: true,
        // I have autocomplete, but TS complains about the lack of prop2
   }
}
function PartialFooMaker2(): FooType {
   return {
        prop2: true,
        // I have autocomplete, but TS complains about the lack of prop1
   }
}

export const Foo: FooType = Object.assign({}, PartialFooMaker1(),PartialFooMaker2());

选项三

我可以将完整类型指定为函数返回类型,但是如果我省略一些属性,那将(正确)触发编译错误。

function PartialFooMaker1(): Partial<FooType> {
   return {
        prop1: true,
        // I have autocomplete! :)
   }
}
function PartialFooMaker2(): Partial<FooType> {
   return {
        prop2: true,
        // I have autocomplete! :)
   }
}

// the compile error is now here - TS doesn't know that prop1 and prop2 are present
export const Foo: FooType = Object.assign({}, PartialFooMaker1(),PartialFooMaker2());

我还考虑过将FooType拆分为定义明确的子类型,然后与并集类型重新组合,但是实际上它是一个复杂的派生类型,因此对我来说很难拆分。

还有什么我可以尝试的吗?

2 个答案:

答案 0 :(得分:0)

如果可以(合理)使用Pick

interface NamePart { first: string; last: string }
interface AgePart  { age: number; }
interface FooType extends NamePart, AgePart
{
    oneMoreThing: string;
}

function PartialFooMaker1(): Pick<FooType, keyof NamePart | "oneMoreThing">
{
    return {
        first: "Steve",
        last: "Stevenson",
        oneMoreThing: "!",
    }
}
function PartialFooMaker2(): Pick<FooType, keyof AgePart>
{
    return {
        age: 42
    }
}

export const Foo: FooType = { ...PartialFooMaker1(), ...PartialFooMaker2() };

第一部分将具有解析的类型Pick<FooType, "first" | "last" | "oneMoreThing">,该类型与Pick<FooType, "age">正确组合以形成FooType的完整实例。

可以从类型安全的文字和keyof表达式中合并键。

答案 1 :(得分:0)

Partial表示共有零个或多个属性。您想要的是Pick

function PartialFooMaker1(): Pick<FooType, 'prop1'> {
  return {
       prop1: true,
       // I want autocomplete in here
  };
}

function PartialFooMaker2(): Pick<FooType, 'prop2'> {
  return {
       prop2: true,
       // I also want autocomplete in here
  };
}

使用Pick将要求您提供要预先选择的属性,但是这将为您提供IntelliSense。

另一种选择是告诉TypeScript每个工厂函数都返回一个FooType

type Slice<T extends object> = { [P in keyof T]: Pick<T, P> }[keyof T];

type FooFactory = () => Slice<FooType>;

const PartialFooMaker3: FooFactory = () => {
  return {
    prop1: false,
  };
};

这不需要显式的返回类型,但是推断的类型将始终是FooType a 切片,而不是{{1}的 the 切片}您实际上正在返回。这就是为什么我建议采用第一方法。如果您未说明所需的返回类型,则IntelliSense不会建议您返回什么。