443 votes

Existe-t-il une `valueof` similaire à` keyof` dans TypeScript?

Je veux être en mesure d'attribuer une propriété de l'objet à une valeur donnée d'une clé et d'une valeur en tant qu'entrées mais encore être en mesure de déterminer le type de la valeur. C'est un peu difficile à expliquer donc ce code doit apparaître le problème:

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

J'ai essayé de changer value: any de value: valueof JWT mais cela ne fonctionne pas.

Idéalement, onChange('expire', 1337) échoue parce qu' 1337 n'est pas un type de Date.

Comment puis-je changer d' value: any de la valeur de la clé donnée?

745voto

jcalz Points 30410

Mise à JOUR: il Semble bien que la question du titre qui attire les gens à la recherche pour une union de tous les possibles valeur de la propriété de types, analogue à la façon de keyof vous donne l'union de tous les possibles de la propriété des types de clés. Nous allons aider ces gens-là en premier. Vous pouvez faire un ValueOf analogue keyof, par l'utilisation de types de requêtes avec keyof T que la clé de la sorte:

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

qui vous donne

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

Pour la question, comme indiqué, vous pouvez utiliser les touches individuelles, plus étroit que d' keyof T, pour extraire juste le type de valeur que vous vous souciez d':

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

Afin de s'assurer que la paire clé/valeur "match up" correctement dans une fonction, vous devez utiliser les génériques ainsi que de types de requêtes, comme ceci:

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

L'idée est que l' key paramètre permet au compilateur de déduire le générique K paramètre. Alors il faut qu' value correspond JWT[K], la recherche de type dont vous avez besoin.

Espérons que cette aide, bonne chance!

85voto

Chris Kowalski Points 356

Si quelqu'un cherche toujours une implémentation de valueof à quelque fin que ce soit, voici un exemple que j'ai proposé:

 type valueof<T> = T[keyof T]
 

Usage:

 type actions = {
  a: {
    type: 'Reset'
    data: number
  }
  b: {
    type: 'Apply'
    data: string
  }
}
type actionValues = valueof<actions>
 

Fonctionne comme prévu :) Retourne une union de tous les types possibles

8voto

Billy Chan Points 14916

Merci les réponses existantes qui résolvent le problème parfaitement. Je voulais juste ajouter qu'une bibliothèque a inclus ce type d'utilitaire, si vous préférez importer celui-ci.

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>;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X