【问题标题】:TypeScript: how to use a Generics Array of objects where one object value inherits type definitions from another object valueTypeScript:如何使用泛型对象数组,其中一个对象值从另一个对象值继承类型定义
【发布时间】:2022-10-30 04:49:23
【问题描述】:

我正在尝试获取对象数组的类型继承,其中一个对象值类型应该从另一个对象值继承类型。我怀疑这是否可能,但值得一试。现在我认为我最好的选择是使用对象而不是数组来解决它。

这个例子是based on the answer 有人问类似的问题。

一直到示例 1 的底部,它没有为对象键 'y' 给出错误。这应该会给出一个错误,因为它不在 initialValue.inherit 对象中。

// Example 1

type FinalValues<T extends Array<{ initialValue: { inherit: any } }>> = {
    [P in keyof T]: T[P] extends { initialValue: infer I extends { inherit: any } } ? { initialValue: I, finalValue: I['inherit'] }: never 
}

function myFunc<T extends [{ initialValue: { inherit: any } }] | Array<{ initialValue: { inherit: any } }>>(v: T & FinalValues<T>) {

}

myFunc([
  {
    initialValue: { inherit: { x: 6 } }, // number
    finalValue: { x: 6 }, // number
  },
  {
    initialValue: { inherit: { y: "hello" } }, // string
    finalValue: { y: "bye" }, // string
  },
]);

myFunc([
  {
    initialValue: { inherit: { x: "hello" , y: 1} }, // string/number
    finalValue: { x: 6, y: 1 }, // err (x should be a string)
  },
  {
    initialValue: { inherit: { a: 'hello' } }, // string
    finalValue: { a: 6,  }, // err (a should be a string)
  },
  {
    initialValue: { inherit: { z: 'hello' } }, // string
    finalValue: { y: 1, z: 'hello' }, // this doesnt error but it should (y is not in initialValue.inherit) 
  },
]);

// Example 2

interface TypeOne {
  options: { someBool?: boolean; someString: string };
}
interface TypeTwo {
  options: { otherKeyBool: boolean };
}

const exampleOne: TypeOne = {
  options: { someBool: true, someString: 'hello' },
};
const exampleTwo: TypeTwo = { options: { otherKeyBool: true } };

interface PassedOptionsType {
  options: Record<string, number | boolean | string>;
}

type ConsumerArrayType<T extends PassedOptionsType[]> = {
  [K in keyof T]: {
    passedOptions: T[K];
    typedBasedOn: T[K]["options"];
  };
};

const consumerFn = <T extends PassedOptionsType[]>(arr: ConsumerArrayType<T>) => null;

consumerFn([
  {
    passedOptions: exampleOne,
    typedBasedOn: {
      // is valid:
      someString: 'valid string',
      // errors correctly:
      unknownKey: 'bla', // invalid key
    },
  },
  {
    passedOptions: exampleTwo,
    typedBasedOn: {
      // is valid:
      otherKeyBool: true,
      
      // is NOT working as expected as its an object key
      // of exampleOne.options and not of exampleTwo.options
      // this should give an type error
      someString: 'invalid type',
    },
  },
]);

【问题讨论】:

  • 我不明白这里什么和什么不应该出错......“从所有传递的对象继承类型”也很模糊;你能澄清问题和期望吗?
  • 也许示例 1 更清楚(更新为与我在其他人的问题上找到的答案相同)

标签: typescript


【解决方案1】:

原来你只需要将数组推断为元组:

const consumerFn = <T extends PassedOptionsType[]>(arr: [...ConsumerArrayType<T>]) => null;

现在它可以正常工作了。

Playground

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多