1

As I filtered vehicles based on isCar so Ts should infer it as an array of Cars but TS infer it as Foo[]. How can I have a conditional type based on isCar??

interface Vehicle {
  driveName: string
}

interface Bicycle extends Vehicle {
  isCar: false,
  saddleColor: string
}

interface Car extends Vehicle {
  isCar: true
  plate: string
}


type Foo = Bicycle | Car


const vehicles: Foo[] = [
  {
    driveName: "foo",
    isCar: true,
    plate: "1111"
  },
  {
    driveName: "bar",
    isCar: false,
    saddleColor: "red"
  }
]


const c = vehicles.filter(({ isCar }) => isCar) // typeof c is not Car

my code

I found these questions but was not able to find an answer to my problem

Typescript Interface - Possible to make "one or the other" properties required?

Typescript asserting types if they have one property true or false

  • Please include your code in the question. So people can see your problem without leaving SO. – Eldar Oct 27 '22 at 06:41
  • @Eldar I'm new to stackoverflow and not able to post image. follow the link I put in post – mohammadizanloo55 Oct 27 '22 at 06:56
  • Does one these posts: [Why can't TypeScript infer type from filtered arrays?](https://stackoverflow.com/questions/62032214/why-cant-typescript-infer-type-from-filtered-arrays) or [Way to tell TypeScript compiler Array.prototype.filter removes certain types from an array?](https://stackoverflow.com/questions/43010737/way-to-tell-typescript-compiler-array-prototype-filter-removes-certain-types-fro) , answer your question? – Palladium02 Oct 27 '22 at 07:21
  • @mohammadizanloo55 please always include minimum reproducible example in your question, otherwise your question will probably be closed – captain-yossarian from Ukraine Oct 27 '22 at 07:29

1 Answers1

1

You need to use custom typeguard:

interface Vehicle {
  driveName: string
}

interface Bicycle extends Vehicle {
  isCar: false,
  saddleColor: string
}

interface Car extends Vehicle {
  isCar: true
  plate: string
}


type Foo = Bicycle | Car


const vehicles: Foo[] = [
  {
    driveName: "foo",
    isCar: true,
    plate: "1111"
  },
  {
    driveName: "bar",
    isCar: false,
    saddleColor: "red"
  }
]

const isCar = (vehicle: Foo): vehicle is Car => vehicle.isCar

const c = vehicles.filter(isCar) // typeof c is not Car

Playground