Subtyping function arguments with stream type

I have several types in my applications that have several common attributes. I dropped common attributes into a separate type. Now I would like to write a function that accepts any type that has a base type.

This few lines explains the problem much better than words:

type Box = {
  width: number,
  height: number,
}

// is like Box + it has position
type PositionedBox = Box & {
  type: 'positionedBox',
  left: number,
  top: number,
}

// is like Box + it has colo
type ColorBox = Box & {
  type: 'colorBox',
  color: string,
}

const logSize = (obj: Box) => {
  console.log({ w: obj.width, h: obj.height });
};

const logPosition = (obj: PositionedBox) => {
  console.log({ l: obj.left, t: obj.top });
};

const logColor = (obj: ColorBox) => {
  console.log({color: obj.color});
};

// this function should accept any Box like type
const logBox = (obj: Box) => {
  logBox(obj);
  // $ERROR - obj Box has no type property
  // (make sense at some point, but how to avoid it?)
  if (obj.type === 'colorBox') logColor(obj);
  if (obj.type === 'positionedBox') logPosition(obj);
}

Question: What should the function declaration look like logBox()to pass the flow check.

+4
source share
1 answer

, {width: 5, height: 5, type: 'colorBox'} logBox, Box. - Box, , type, - .

Box, disjoint union. Box BaseBox Box, . .

type BaseBox = {
  width: number,
  height: number,
}

// is like Box + it has position
type PositionedBox = BaseBox & {
  type: 'positionedBox',
  left: number,
  top: number,
}

// is like Box + it has colo
type ColorBox = BaseBox & {
  type: 'colorBox',
  color: string,
}

type Box = PositionedBox | ColorBox;

const logSize = (obj: Box) => {
  console.log({ w: obj.width, h: obj.height });
};

const logPosition = (obj: PositionedBox) => {
  console.log({ l: obj.left, t: obj.top });
};

const logColor = (obj: ColorBox) => {
  console.log({color: obj.color});
};

// this function should accept any Box like type
const logBox = (obj: Box) => {
  logBox(obj);
  // $ERROR - obj Box has no type property
  // (make sense at some point, but how to avoid it?)
  if (obj.type === 'colorBox') logColor(obj);
  if (obj.type === 'positionedBox') logPosition(obj);
}
+1

Source: https://habr.com/ru/post/1681249/


All Articles