Search code examples
typescriptliteralscomputed-properties

Creating computed class properties from array


I have an array of string literals that I'd like to use as property names for a class.

const propNames = ["a", "b", "c"] as const;

I would like to create a class like

class Test {
    [name in typeof propNames[number]]: any;
}

But this gives the errors (in WebStorm inspection):

TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.
TS2693: 'number' only refers to a type, but is being used as a value here.

I can instead define a type with those properties like

type Test = {
    [name in typeof propNames[number]]: any;
}

But I don't know a way of turning this into a class with those properties.

I have an extra question that I don't think is possible currently, but could I create those property names by concatenating another string literal to them?

type Test = {
    [name + 'Prop' in typeof propNames[number]]: any;
}

Solution

  • I got around this (including the extra question) by defining intermediate types and using them like namespaces:

    const propNames = ["a", "b", "c"] as const;
    
    // using DOM types for demonstration
    type Canvases {
        [name in typeof propNames[number]]?: HTMLCanvasElement;
    }
    type Contexts {
        [name in typeof propNames[number]]?: CanvasRenderingContext2D;
    }
    
    // define class
    class Test {
        canvases: Canvases = {};
        ctxs: Contexts = {};
    }
    
    // now access on instances
    const t = new Test();
    t.canvases.a; // HTMLCanvasElement
    t.ctxs.b;     // CanvasRenderingContext2D