typescript 通过Object属性键和Object类型获取对象属性值的类型

a64a0gku  于 2023-01-14  发布在  TypeScript
关注(0)|答案(2)|浏览(362)

我有一个对象的类型和该类型对象的键。如何得到键对应值的类型?
我有以下功能:

function toPartial<T>(key: keyof T, value: T[typeof key]): Partial<T> {
  const partial: Partial<T> = {};
  partial[key] = value;
  return partial;
}

value的当前类型是错误的,因为它包含了所有键的类型与键的类型。
示例:

type ExampleType = {
  id: string,
  amount: number
}

const key = "amount";
const value = "abc"

toPartial<ExampleType>(key, value); // with my implementation there is no type error, but it should because a string is not assignable to `amount` of `Example type`.
ddhy6vgd

ddhy6vgd1#

类似的方法很有效:

function toPartial<T, U extends keyof T>(key: U, value: T[U]): Partial<Pick<T, U>> {
  const partial: Partial<T> = {};
  partial[key] = value;
  return partial;
}

type ExampleType = {
  id: string,
  amount: number
}

const foo = toPartial<ExampleType, "amount">("amount", 3);

该值与键相链接。另外,返回类型可能会通过使用Pick得到改进!
Playground

5n0oy7gb

5n0oy7gb2#

这完全可以通过inference的参数来完成,但是需要一个higher-order辅助函数来创建适当的约束。
这是因为TypeScript当前不允许只提供 * 一些 * 泛型类型参数:目前要么全部要么没有。你可以在下面的GitHub问题上阅读更多信息:microsoft/TypeScript#10571 - Allow skipping some generics when calling a function with multiple generics
下面是helper函数的外观:

type PartialFactoryFn<T extends Record<PropertyKey, unknown>> =
  <K extends keyof T, V extends T[K]>(key: K, value: V) => Partial<T>;

/** @returns the `toPartial` function that you described in your question */
function createPartialFactory <T extends Record<PropertyKey, unknown>>(): PartialFactoryFn<T> {
  return (key, value) => {
    const partial: Partial<T> = {};
    partial[key] = value;
    return partial;
  };
}

您可以通过以下方式将其用于示例类型和值:

type Example = {
  amount: number;
  id: string;
};

const partialExampleError = createPartialFactory<Example>()("amount", "abc"); /* Error
                                                                      ~~~~~
Argument of type 'string' is not assignable to parameter of type 'number'.(2345) */

const partialExample = createPartialFactory<Example>()("amount", 10); // ok

partialExample.amount;
             //^? (property) amount?: number | undefined
partialExample.id;
             //^? (property) id?: string | undefined

如果你想创建一个受特定类型约束的专用函数(例如你的示例类型),你也可以这样写:

const toPartialExample = createPartialFactory<Example>();

toPartialExample("amount", "abc"); /* Error
                           ~~~~~
Argument of type 'string' is not assignable to parameter of type 'number'.(2345) */

toPartialExample("amount", 10); // ok

TSPlayground的代码

相关问题