1. ホーム
  2. タイプスクリプト

[解決済み】TypeScriptで`keyof`に似た`valueof`はありますか?

2022-04-20 04:31:28

質問

キーと値を入力として、オブジェクトのプロパティを値に割り当てたいのですが、値の型を決定することができます。ちょっと説明しにくいので、このコードで問題を明らかにします。

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: anyvalue: valueof JWT が、うまくいかなかった。

理想は onChange('expire', 1337) は失敗します。 1337 はDate型ではありません。

を変更するにはどうすればよいですか? value: any を指定されたキーの値にすることはできますか?

どのように解決するのですか?

UPDATE: 質問のタイトルは、可能なすべてのプロパティ値のタイプのユニオンを探している人々を引きつけているようです。 keyof は、可能なすべてのプロパティ・キー・タイプの組合わせを提供します。 まず、そのような人たちを助けてあげましょう。 あなたは ValueOf に類似した keyof を使用することで インデックス付きアクセスタイプ keyof T をキーにして、このようにします。

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

で、これは

type Foo = { a: string, b: number };
type ValueOfFoo = ValueOf<Foo>; // string | number


記載されている質問については、個別のキーで、狭義の keyof T のように、気になる値型だけを抽出することができます。

type sameAsString = Foo['a']; // look up a in Foo
type sameAsNumber = Foo['b']; // look up b in Foo

関数の中でキーと値のペア "マッチング"が正しく行われるようにするためには ジェネリックス というように、インデックス付きのアクセスタイプもあります。

declare function onChange<K extends keyof JWT>(key: K, value: JWT[K]): void; 
onChange('id', 'def456'); // okay
onChange('expire', new Date(2018, 3, 14)); // okay
onChange('expire', 1337); // error. 1337 not assignable to Date

という考え方です。 key パラメータを使うことで、コンパイラは一般的な K パラメータを使用します。 そして、そのためには value マッチ JWT[K] のように、必要なインデックス付きアクセスタイプを指定します。