Typescript: Is it possible to dynamically assign the type of an object?

Viewed 27

I'm getting the following eslint error "@typescript-eslint/no-unsafe-assignment". This is because I am trying to access certain keys and values from a variable that gets assigned different kind of objects which type can be of about 10 classes.

// var **key** can be any property of object1 and depending on which property 
// the result will be an object that is of multiple different types
Object.keys(object1).forEach((key) => {

    const object2 = object1[key]; // depending on key this can be of type class A, B, C, D and so on

    Object.getOwnPropertyNames(object2).forEach((property) => {
        // ESLINT error because linter does not know the type of object2
        // which could be multiple classes depending on key
        const var1 = object2[property]

I tried the following but this of course does not work. How could I do this when I don't know the type of my object yet because I'm looping through them.

// properties with **class type** values
const objectTypes = {
    first: A,
    second: B,
    third: C,
    fourth: D,
}
....
....
// Then based on the property that is the same value as the key to get object2
// I get the correct type from my objectTypes
const var1Type = objectTypes[key];
const var1 = (object2 as var1Type)[property];
1 Answers

The type of the value returned by Object.keys(obj) or Object.getOwnPropertyNames(obj) is string[] not Array<keyof typeof obj>. The reason for this is that an object can be typed more tightly than its actual value. For example:

type MyType = {
    foo: string,
};

// Inferred type
const myObj = {
    foo: 'test',
    bar: 1,
};

// Explicit type
const myTypedObj: MyType = myObj;

const keys = Object.keys(myTypedObj); // `myTypedObj` is of type `MyType`, but `keys` is ['foo', 'bar'] not just ['foo']
console.log(keys);

TypeScript Playground

If you want to loop through an object's keys using Object.keys, you should also filter it down to just the keys that your type knows about. That way, TypeScript will know the type of the property you're trying to access.

From your linting error, it sounds like TypeScript is inferring the property type as any, so assigning it is unsafe because type checks aren't done on values with type any.

Related