我希望能够将对象属性分配给一个值,给定一个键和值作为输入,但仍然能够确定值的类型。这有点难以解释,所以这段代码应该揭示了问题:

type JWT = { id: string, token: string, expire: Date };
const obj: JWT = { id: 'abc123', token: 'tk01', expire: new Date(2018, 2, 14) };

function print(key: keyof JWT) {
    switch (key) {
        case 'id':
        case 'token':
            console.log(obj[key].toUpperCase());
            break;
        case 'expire':
            console.log(obj[key].toISOString());
            break;
    }
}

function onChange(key: keyof JWT, value: any) {
    switch (key) {
        case 'id':
        case 'token':
            obj[key] = value + ' (assigned)';
            break;
        case 'expire':
            obj[key] = value;
            break;
    }
}

print('id');
print('expire');
onChange('id', 'def456');
onChange('expire', new Date(2018, 3, 14));
print('id');
print('expire');

onChange('expire', 1337); // should fail here at compile time
print('expire'); // actually fails here at run time

我试着将value: any改为value: valueof JWT,但没有成功。

理想情况下,onChange('expire', 1337)会失败,因为1337不是Date类型。

如何将value: any更改为给定键的值?


当前回答

还有另一种方法提取对象的联合类型:

  const myObj = { a: 1, b: 'some_string' } as const;
  type values = typeof myObj[keyof typeof myObj];

结果:1 | "some_string"

其他回答

还有另一种方法提取对象的联合类型:

  const myObj = { a: 1, b: 'some_string' } as const;
  type values = typeof myObj[keyof typeof myObj];

结果:1 | "some_string"

感谢现有的答案,完美地解决了这个问题。只是想添加一个库已经包括这个实用程序类型,如果你更喜欢导入这个常见的。

https://github.com/piotrwitek/utility-types#valuestypet

import { ValuesType } from 'utility-types';

type Props = { name: string; age: number; visible: boolean };
// Expect: string | number | boolean
type PropsValues = ValuesType<Props>;

一行程序:

type ValueTypesOfPropFromMyCoolType = MyCoolType[keyof MyCoolType];

泛型方法示例:

declare function doStuff<V extends MyCoolType[keyof MyCoolType]>(propertyName: keyof MyCoolType, value: V) => void;

你可以为你自己创建一个Generic来获取值的类型,但是,请考虑object的声明应该声明为const,比如:

export const APP_ENTITIES = {
  person: 'PERSON',
  page: 'PAGE',
} as const; <--- this `as const` I meant

然后下面的泛型将正常工作:

export type ValueOf<T> = T[keyof T];

现在像下面这样使用它:

const entity: ValueOf<typeof APP_ENTITIES> = 'P...'; // ... means typing

   // it refers 'PAGE' and 'PERSON' to you

我知道这有点离题了,每次我都在寻找解决方法。我被派到这个岗位。对于那些正在寻找字符串文字类型生成器的人,这里。

这将从对象类型创建一个字符串文字列表。

export type StringLiteralList<T, K extends keyof T> = T[keyof Pick<T, K>];

type DogNameType = { name: "Bob", breed: "Boxer" } | { name: "Pepper", breed: "Spaniel" } | { name: "Polly", breed: "Spaniel" };

export type DogNames = StringLiteralList<DogNameType, "name">;

// type DogNames = "Bob" | "Pepper" | "Polly";