Home > Mobile >  How can I handle the different types in typescript?
How can I handle the different types in typescript?

Time:06-17

I'm trying to understand how typescript works here. For object with similar object properties, I'm able to handle. But how about something like this?

Shape has different object values. How can I run this function without an error?

type Shape =
  | { kind: "circle"; radius: number }
  | { data: "square"; x: number };

function area(s: Shape) {
  if (s.kind === "circle") {
    return Math.PI * s.radius * s.radius;
  } else {
    return s.x * s.x;
  }
}

PS: This is a broken code.

CodePudding user response:

You need to have kind property for both circle and square.

Below should work.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; x: number };

function area(s: Shape) {
  if (s.kind === "circle") {
    return Math.PI * s.radius * s.radius;
  } else {
    return s.x * s.x;
  }
}

CodePudding user response:

If you are unable to change the format of the data coming in so that all types of shapes have a kind property with a unique value, then the following will work, but it isn't the best code:

interface Circle {
  kind: 'circle'; 
  radius: number;
}

interface Square {
  data: 'square';
  x: number;
}

type Shape = Circle | Square;

function area(s: Shape) {
  if ('kind' in s && s.kind === 'circle') {
    return Math.PI * s.radius * s.radius;
  } else {
    const sq = s as Square;
    return sq.x * sq.x;
  }
}

Note that I defined separate interfaces for each type of shape so that I can easily cast s to one of them.


A better approach: type predicates

If you plan on using this Shape type in quite a few different methods, then it would be helpful to create custom type predicate functions that allow you to return a boolean that indicates if a Shape variable is a specific type of shape. TypeScript will treat the variable in all statements within an if block calling that function as the subtype.

In code, if we assume we have the same Circle, Square and Shape types I defined above, the code below that would change to:

function isCircle(s: Shape): s is Circle {
  return 'kind' in s && s.kind === 'circle';
}

function isSquare(s: Shape): s is Square {
  return 'data' in s && s.data === 'square';
}

function area(s: Shape) {
  if (isCircle(s)) {
    // Within this block, TS knows that s is a Circle.
    // So trying to do `s.x` would be an error, for example.
    return Math.PI * s.radius * s.radius;
  } else if (isSquare(s)) {
    // Within this block, TS knows that s is a Square.
    // So trying to do `s.radius` would be an error, for example.
    return s.x * s.x;
  }
  throw new Error(`Unknown shape type: ${JSON.stringify(s)}`);
}
  • Related