Home:ALL Converter>Typescript: interface that extends a JSON type

Typescript: interface that extends a JSON type

Ask Time:2022-08-08T23:54:58         Author:theahura

Json Formatter

I am using a generic JSON type in typescript, suggested from here

type JSONValue = 
 | string
 | number
 | boolean
 | null
 | JSONValue[]
 | {[key: string]: JSONValue}

I want to be able to cast from interface types that match JSON to and from the JSON type. For example:

interface Foo {
  name: 'FOO',
  fooProp: string
}

interface Bar {
  name: 'BAR',
  barProp: number;
}

const genericCall = (data: {[key: string]: JSONValue}): Foo | Bar | null => {
  if ('name' in data && data['name'] === 'FOO')
    return data as Foo;
  else if ('name' in data && data['name'] === 'BAR')
    return data as Bar;
  return null;
}

This currently fails because Typescript does not see how the interface could be of the same type as JSONValue:

Conversion of type '{ [key: string]: JSONValue; }' to type 'Foo' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'name' is missing in type '{ [key: string]: JSONValue; }' but required in type 'Foo'.

but analytically we of course know this is ok, because we recognize that at runtime types Foo and Bar are JSON compatible. How do I tell typescript that this is an ok cast?

ETA: I can follow the error message and cast to unknown first, but I'd rather not do that -- it would be better if TS actually understood the difference, and I'm wondering if it's possible at all.

Author:theahura,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/73280790/typescript-interface-that-extends-a-json-type
yy