1

There are like these types

interface A {
  id: number
  name: string
  patternA: patternA[]
}

interface B {
  id: number
  name: string
  patternB: patternB[]
}

interface C {
  id: number
  name: string
  patternC: patternC[]
  city: string
}

and there is factory method

const factory = (type, data: /** 🤔 what should I write?? **/) => {
  switch (type) {
    case 'first':
      return createHogeA(data)
    case 'second':
      return createHogeB(data)
    case 'third':
      return createHogeC(data)
    default:
      return
  }
}

const createHogeA = (data: A) => somefunctionA(data)
const createHogeB = (data: B) => somefunctionB(data)
const createHogeC = (data: C) => somefunctionC(data)

What I've tried so far

  1. Set type like this, but then appears error because it's possible that each datas type could pass to each functions
const factory = (type, data: A | B | C) => {
  switch (type) {
    case 'first':
      return createHogeA(data)
    case 'second':
      return createHogeB(data)
    case 'third':
      return createHogeC(data)
    default:
      return
  }
}
  1. Create base interface
interface base {
  id: number
  name: string
}

But then honestly I didn't have idea

1
  • how do you intend to call your factory? where does type come from? Commented Mar 30, 2023 at 7:05

2 Answers 2

0

Perhaps via type union discrimination:

interface A {
  type: 'A'
  id: number
  name: string
  patternA: patternA[]
}

interface B {
  type: 'B'
  id: number
  name: string
  patternB: patternB[]
}

interface C {
  type: 'C'
  id: number
  name: string
  patternC: patternC[]
  city: string
}

type ABC = A | B | C;

const factory = (data: ABC) => {
  switch (data.type) {
    case 'A':
      return createHogeA(data)
    case 'B':
      return createHogeB(data)
    case 'C':
      return createHogeC(data)
    default:
      return
  }
}
Sign up to request clarification or add additional context in comments.

Comments

-1

The easiest way to handle this is to use the as keyword to tell the compiler which of the interfaces the data object satisfies when calling either of the functions.

const factory = (type: string, data: A | B | C) => {
  switch (type) {
    case 'first':
      return createHogeA(data as A)
    case 'second':
      return createHogeB(data as B)
    case 'third':
      return createHogeC(data as C)
    default:
      return
  }
}

You could also use guards to determine which interface data satisfies

const isA = (data: any): data is A => {
  return (data as A).patternA !== undefined;
}

const isB = (data: any): data is B => {
  return (data as B).patternB !== undefined;
}

const isC = (data: any): data is C => {
  return (data as C).patternC !== undefined && (data as C).city !== undefined;
}

const factory = (_type: string, data: A | B | C) => {
  if(isA(data)) {
    createHogeA(data)
  }
  // Rest of code here
}

1 Comment

I've tried it and it resolved, thank you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.