Búsqueda de sitios web

typescript - Cómo establecer los valores de un objeto en función de la propiedad/clave


Estoy aprendiendo Typescript y tratando de entender cómo establecer el tipo de un objeto basado en la clave (literal de plantilla)

Aquí está el ejemplo:

interface Circle {
  radius: number;
}

interface Square {
  length: number;
}

type TypeName = "circle" | "square"; 
type ObjectType<T> = 
  T extends "circle" ? Circle :
  T extends "square" ? Square :
  never

type Shape = {
    [id: `${TypeName}.${string}`]: ObjectType<TypeName>
}

const circle:Shape = {"circle.anythig": {length: 33}} // Square??
                   //  ^^^^^^ how to force the type based on object property key name?
const square:Shape = {"square.anythig": {length: 33}} // Square 

Patio de recreo

Respuesta #1

Puedes usar un tipo mapeado con reasignación de claves para asociar un TypeName dado con su ObjectType correspondiente.

type Shape = {
    [ID in TypeName as `${ID}.${string}`]: ObjectType<ID>
}

Esto llevará al error deseado si los tipos no coinciden.

const shape: Shape = { 
  "circle.anything": { length: 33 },
                   //  ^^^^^^ Type '{ length: number; }' is not assignable to type 'Circle'
  "square.anything": { length: 33 }
}

Parque infantil

Respuesta #2

Aquí hay otra implementación, por si alguien está interesado:

interface Circle {
  radius: number;
}

interface Square {
  length: number;
}

type Shapes = {
  circle: Circle
  square: Square
}

type TypeName = "circle" | "square"; 

type Shape = {
    [ID in keyof Shapes as`${ID}.${string}`]: Shapes[ID]
}

const t:Shape = {"square.foo": {length: 33}}