function getColors(
    url: string,
    config: Config
  ): Promise<Result>;
}

type Config = {
  dominant?: boolean;
  average?: boolean;
};

type Result = {
  dominant?: string;
  average?: string;
};

¿Cómo puedo decir si dominant se pasó como true al objeto de configuración, p. getColors (url, { dominante: verdadero}) , entonces no es opcional en Result.

async () => {
  let example : string;

  const colors = await getColors(url, {dominant: true});
  example = colors.dominant;
                 // ^^^^^^ Type 'string | undefined' is not assignable to type 'string'.
                 //        Type 'undefined' is not assignable to type 'string'
};
3
Osama Qarem 25 feb. 2020 a las 16:06

2 respuestas

La mejor respuesta

Podemos hacerlo tipos condicionales. Considerar:

type Config = {
  dominant?: boolean;
  average?: boolean;
};

type Result = {
  dominant?: string;
  average?: string;
};

declare function getColors<C extends Config>(
    url: string,
    config: C
): Promise<Result & (C['dominant'] extends true ? {dominant: string} : {})>;


async function f() {
  const colors = await getColors('url', { dominant: true })
  colors.dominant // is non-optional string
}

Lo esencial es tener Config como genérico en getColors y agregar un comportamiento condicional en el tipo de retorno: Result & (C['dominant'] extends true ? {dominant: string} : {}). Lo que hacemos aquí es: si dominant es verdadero en la configuración, intersectamos con nuestro objeto de tipo que tiene dominant requerido, si dominant es falso, intersectamos con {} que es neutral elemento, por lo que recuperamos Result.

Patio de recreo

4
Maciej Sikora 25 feb. 2020 a las 13:44

Puede proporcionar dos firmas sobrecargando la función:

interface Config { average?: boolean, dominant?: boolean }
interface ConfigDominant extends Config { dominant: true }

interface Result { average?: string, dominant?: string }
interface ResultDominant extends Result { dominant: string }

// more specific signature must go first
function getColors(url: string, config: ConfigDominant): Promise<ResultDominant>;
// less specific signature
function getColors(url: string, config: Config): Promise<Result>;
// implementation
function getColors(url: string, config: Config): Promise<Result> {
    throw new Error('not implemented');
}

async (url: string) => {
    const colors = await getColors(url, {dominant: true});
    // no error here
    let example: string = colors.dominant;
};

Enlace de juegos

2
kaya3 25 feb. 2020 a las 13:39