Mecanografiado opcionalmente ampliando la interfaz

4 minutos de lectura

Avatar de usuario de Louie Bertoncin
Louie Bertoncin

tengo dos interfaces, uno de los cuales prolonga al otro. Sin embargo, me gustaría poder extender la primera interface y hacer que todos sus tipos sean opcionales. No quiero tener que volver a escribir todas las definiciones de la primera interface ser opcional en mi segundo interface (porque ¿cuál es la ventaja de extender en ese punto?) o redefinir la primera interface porque se está utilizando en otros lugares.

Lo que parece:

interface First {
  type1: string
  type2: string
}

// Seemingly pointless rewrite (why would I even need to extend?)
interface Second extends First {
  type1?: string
  type2?: string
  type3: string
  type4: string
}

// What I imagine the extending should be (but doesn't work)
interface Second extends First? {
  type3: string
  type4: string
}

Investigué y encontré esta pregunta que responde algo muy similar, pero ha pasado un año desde que se tocó esa pregunta y creo que mi problema no es exactamente el mismo porque quiero hacer el completo extendido interface opcional, no solo algunos tipos de él.

¿Hay alguna manera de hacer esto en TypeScript, o solo necesito absorberlo y hacer un segundo largo? interface?


Actualización (para explicar por qué me gustaría tener este trabajo):

Estoy escribiendo una aplicación web React y tengo un componente que muestra una entidad de mi base de datos de una manera que permite al usuario editar cualquier valor de esa entidad. Me gustaría que mi componente React maneje el caso en el que el usuario está creando una nueva entidad, así como el caso en el que el usuario está editando una entidad existente.

Para seguir con mi ejemplo anterior, digamos que los valores de la entidad de mi base de datos son replicados por el Primero interface y el componente React usa dos accesorios pasados ​​​​que existen en el Segundo interface. El componente React siempre tienen los dos valores en el Segundopero no necesariamente tienen los valores de la Primero.

En el caso de que el usuario cree una nueva entidad, me gustaría construir el componente React solo con los valores de Segundosin tener que especificar null valores para todo en Primero. En el caso de que el usuario edite una entidad existente, pasaría todo, desde Primero y Segundo.

En ambos casos, sería la misma interfaz de usuario, pero construida con un conjunto diferente de valores.

  • cual es el escenario en tu caso. Actualizar a la publicación te ayudará

    – Aravind

    21 mayo 2017 a las 20:38

Puedes usar alias de tipo junto con un intersección sobre el Parcial escribe:

type First = {
    type1: string;
    type2: string;
}

type Second = Partial<First> & {
    type3: string;
    type4: string;
}

  • Eres un regalo del cielo. Eso lo hizo por mí. En todo el tiempo que he estado usando DefinitelyTyped, por ignorancia no he notado el tipo type y han implementado interface en todas partes en mi(s) proyecto(s).

    – Louie Bertoncin

    21 mayo 2017 a las 21:04

  • Son en muchos casos más o menos lo mismo. Asegúrate de leer Interfaces frente a alias de tipo para obtener una mejor comprensión de cómo se diferencian.

    – Nitzan Tomer

    21 mayo 2017 a las 21:07

  • Ahora que soy menos joven e ingenuo, veo el interface Second extends Partial<First> funciona igual de bien (como se muestra en la respuesta de Dibyo a continuación)

    – Louie Bertoncin

    1 de agosto de 2020 a las 1:02

Avatar de usuario de Dibyo Majumdar
Dibyo Majumdar

Puede hacer esto con interfaces usando el Partial escribe.

interface First {
    type1: string;
    type2: string;
}

interface Second extends Partial<First> {
    type3: string;
    type4: string;
}

  • Esta respuesta funciona a partir de TypeScript versión 2.2

    – luiscla27

    10 de diciembre de 2021 a las 2:25


Hay un método mejor/más simple. Usando Omitir puede redefinir solo las propiedades nombradas específicas.

interface First {
    type1: string;
    type2: string;
}

interface Second extends Omit<First, "type1"> {
    type1?: string;
}

  • O en este caso, incluso puedes usar Pict<First, "type2"> en vez de Omit El resultado será el mismo

    – Jakub Kurdziel

    15 abr a las 11:55

También puede hacer que todas las partes sean opcionales proporcionando una interfaz vacía:

export interface ISingleScope {
   scope: string;
}

export interface IMultiScope {
   scopes: string[];
   check?: boolean;
}

export interface IProvidedScope 
   extends Partial<ISingleScope>, Partial<IMultiScope> { 
}

Sin embargo, normalmente esto requerirá una prueba explícita de que existe la propiedad utilizada, ya que en tiempo de ejecución ninguna de estas informaciones está presente. Entonces, si su objeto viene con el nombre opciones que esto sería suficiente:

if (options && options.scopes) {
   // access properly 'IMultiScope'
}

Partial es genial, pero a veces quieres elegir las teclas que quieres hacer opcionales en lugar de hacerlas todas opcionales.

Para hacer eso, usa:
type Optional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>

Fuente: esta respuesta opcional es de esta pregunta si necesita una opción anidada, vaya a la pregunta vinculada.

Avatar de usuario de PRAISER
ALABADOR

Extends en mecanografiado interface significa que el segundo objeto heredará lo que tenga el primer objeto, si las propiedades del primero son opcionales o no, se aplicarán al segundo sin cambios. No puede cambiar este comportamiento en Typescript. La respuesta a tu pregunta que no debes usar extends para tu caso

¿Ha sido útil esta solución?