Is there the Typescript valueof similar to keyof?

Is there the Typescript valueof similar to keyof?

Hi,

You can define a generic function that maps the key to the appropriate value type:

type JWT = { id: string; token: string; expire: Date };

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

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

function onChange<T extends keyof JWT>(key: T, value: JWT[T]) {
    obj[key] = value;
}

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

// Uncommenting the line below will cause a TypeScript error
// onChange('expire', 1337); // Type 'number' is not assignable to type 'Date'

Create a type guard function to check the value type before assignment:

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 isDate(value: any): value is Date {
    return value instanceof Date;
}

function onChange(key: keyof JWT, value: any) {
    if (key === 'expire' && !isDate(value)) {
        throw new Error('Invalid type for expire');
    }
    obj[key] = value;
}

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

// Uncommenting the line below will throw an error at runtime
// onChange('expire', 1337); // Throws Error: Invalid type for expire

Utilize TypeScript’s utility types to ensure correct value types:

type JWT = { id: string; token: string; expire: Date };

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

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

function onChange<K extends keyof JWT>(key: K, value: JWT[K]) {
    obj[key] = value;
}

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

// Uncommenting the line below will cause a TypeScript error
// onChange('expire', 1337); // Type 'number' is not assignable to type 'Date'