Typescript problem with dynamic interfaces according to type

53 views Asked by At

Im working on an Angular 17 app where I have to apply specific interface according to a type in a generic interface.

First, I have the enum with all my block types

export enum BlockTypes {
  text        = 'TEXT',
  check       = 'CHECKBOX',
  header1     = 'HEADER1',
  table       = 'TABLE',
  container   = 'CONTAINER',
};

And it could be added more. So every block type has it's own configuration that I want to have in a separate interface.

// interface for block type Text
export interface BlockText {
    content: string;
}

// interface for block type Text
export interface BlockChecklist {
    list: {
        label: string;
        checked: boolean
    }[];
}

// interface for block type Header
export interface BlockHeader {
    content: string;
    level: number;
}

// interface for block type table
export interface BlockTable {
    fullWidth: boolean;
    columns: string[];
    data: { selected: boolean, data: BlockItem<BlockTypes>[] }[];
}


// interface for block type container
export interface BlockContainer{
    columns: { order: number, data:  BlockItem<BlockTypes>[] }[];
}

So now I want a generic interface named BlockItem to apply the specific interface according to the type I want to create.

So I was trying to create that generic model and send the type as a type parameter, but I'm having an error.

export interface BlockItem<T extends BlockTypes> {
    blockType: T;
    // Here I'm having the error 'Type 'T' cannot be used to index type 'BlockModel'.'
    data: BlockModel[T];
}
  
export interface BlockModel {
    [BlockTypes.text]:      BlockText;
    [BlockTypes.check]:     BlockChecklist;
    [BlockTypes.header1]:   BlockHeader;
    [BlockTypes.table]:     BlockTable;
    [BlockTypes.container]: BlockContainer;
}

The result that I expect is to create variables like this examples:

const exampleBlockText: BlockItem<BlockTypes.text> = {
  blockType: BlockTypes.text,
  data: { content: 'Hello, World!' },
};
const exampleBlockCheck: BlockItem<BlockTypes.check> = {
  blockType: BlockTypes.check,
  data: { list: [ { label: 'Option 1', checked: false }, { label: 'Option 2', checked: false } ] },
};

I'm avoiding to use the "any"type because what I want is to have specific interfaces to each one.

How can I create a generic model with specific interface according to the type sended?

UPDATE:

I am using Angular 17 and this is the tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": false,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "ES2022",
    "useDefineForClassFields": false,
    "lib": [
      "ES2022",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}
0

There are 0 answers