@zWaterFall

Можно ли динамически указывать типы?

Имеется вот такой код:
enum BLOCK_TYPE {
  PARAGRAPH = 'PARAGRAPH',
  IMAGE = 'IMAGE',
  LIST = 'LIST',
}

interface IBlock {
  type: BLOCK_TYPE;
  body: string | string[];
  file?: File;
}


Можно ли сделать так, чтобы
а) При type: "PARAGRAPH" был body: string

б) При type: "IMAGE" был body: File

в) При type: "LIST" был body: string[]
  • Вопрос задан
  • 100 просмотров
Решения вопроса 1
@StockholmSyndrome
type ValueOf<T> = T[keyof T];

const enum BlockType {
  Paragpraph = 'PARAGRAPH',
  Image = 'IMAGE',
  List = 'LIST',
}

interface BodyTypes {
  [BlockType.Paragpraph]: string;
  [BlockType.Image]: File;
  [BlockType.List]: string[];
}

interface IBlock<T extends BlockType> {
  type: T; 
  body: BodyTypes[T];
}

type TBlock = ValueOf<{ [P in BlockType]: IBlock<P> }>;
// type TBlock = IBlock<BlockType.Paragpraph> | IBlock<BlockType.Image> | IBlock<BlockType.List>;


function x(b: TBlock) {
  if (b.type === BlockType.Paragpraph) {
    // b.body is string
  } else if (b.type === BlockType.Image) {
    // b.body is File 
  }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
const enum BlockType {
  Paragpraph = 'PARAGRAPH',
  Image = 'IMAGE',
  List = 'LIST',
}

type IParagraph = {
  type: BlockType.Paragpraph,
  body: string,
}

type IImage ={
  type: BlockType.Image,
  body: File
}

type IList = {
  type: BlockType.List,
  body: string[]
}

function a(x: string){}
function b(x: string[]){}
function c(x: File){}
type IBlock = IParagraph | IImage | IList;
const blocks: IBlock[] = []
for(const block of blocks){
    switch(block.type) {
        case BlockType.Image:
            c(block.body);
            break;      
        case BlockType.Paragpraph:
            a(block.body);
            break;
        case BlockType.List:
            b(block.body);
            break;
    }
}

Playground
Также должно и с интерфейсами работать, просто надо при помощи extends сужать тип
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы