Home > Enterprise >  Typing the value to put into an object property properly
Typing the value to put into an object property properly

Time:10-23

I'm attempting to type the value that I need to put into the property of an object. See below.

interface SliceStateType {
    TrptLimit: number;
    TrptOffset: number;
    someString: string;
    someBool:boolean;

}

interface SettingType {
    key: keyof SliceStateType;
    value: number | string | boolean;
}

const initialState: SliceStateType = {
    TrptLimit: 10,
    TrptOffset: 0,
    someString: 'my string',
    someBool:false,

};

// settings is the same shape as initialState
settings[key] = value as WHATGOESHERE;

I am trying to type value to the exact type of whatever key is. I was thinking maybe WHATGOESHERE would be SliceStateType[typeof key] but that does not work.
The error is Type 'string | number | boolean' is not assignable to type 'never'. Type 'string' is not assignable to type 'never'.

I thought that would have returned the concrete type for that specific key. I am trying to do something like

settings[keyOfSlice] = value as SliceStateType['tRptLimit'];

but replacing tRptLimit with something dynamic based on "key" Any ideas?

CodePudding user response:

function set<T extends Record<never, never>, K extends keyof T>(
  object: T, key: K, value: T[K]
) { 
  object[key] = value;
}

CodePudding user response:

Hmm. I'm not sure if you can do exactly what you're trying to do, but I'm not quite sure what that is. Typescript "erases" the types when it converts to Javascript, so you can't access them "dynamically", which I think is what you are asking.

You can get the type of a specific property, using this notation I don't see in your code:

let foo1: SliceStateType['TrptLimit'] // number

Another thing you can do is extract all the keys from an object type using keyof:

let foo2: keyof SliceStateType = 'TrptLimit' // ok
let foo3: keyof SliceStateType = 'no' // not ok

But you can't write a strongly typed version of settings[someVariable] = value, unless someVariable is typed very specifically to a certain string (or set of strings). What follows are some of the possibilities:

let someVariable: 'TrptLimit' = 'TrptLimit'
settings[someVariable] = ... will expect a number

You can even specify the type as

let someVariable: 'TrptLimit' | 'TrptOffset' = 'TrptLimit'
settings[someVariable] = ... will expect a number

But if someVariable has other keys, you lose some specific type checking:

let someVariable: keyof SliceStateType = 'TrptLimit'
settings[someVariable] = ... number|string|boolean

I hope this helps. This can be confusing initially.

  • Related