Аргумент типа 'строка |undefined 'нельзя назначить параметру типа' "без названия" |ноль |не определено» - PullRequest
0 голосов
/ 26 ноября 2018

Я не могу понять что-то о выводе типа TypeScript.Я думал, что это должно быть допустимо и не требует от меня указывать тип T:

export const deflt = <T>(val: (T | undefined | null), defaultVal: T): T => {
  if (val === undefined || val === null) {
    return defaultVal;
  }
  return val;
}

function maybeLabelName(name: string | undefined) {
  return deflt(name, 'untitled');
}

Вызов deflt завершается неудачно со следующей ошибкой:

Argument of type 'string | undefined' is not assignable to parameter of type '"untitled" | null | undefined'.
  Type 'string' is not assignable to type '"untitled" | null | undefined'. [2345]

Iможно исправить, изменив вызов deflt на один из следующих:

// Option 1:
return deflt<string>(name, 'untitled');

// Option 2:
const s: string = 'untitled';
return deflt(name, s);

Разве TypeScript не должен автоматически выводить тип string?

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

Когда вы используете непатентованные значения, может быть два разных способа «генерирования» параметра.

Используя ваш пример в качестве примера:

const deflt = <T>(val: (T | undefined | null), defaultVal: T): T

Если вы используете: deflt<string>(a, b), то вы заставляете a быть string | undefined | null и b быть string.

Если вы используете: deflt(a: string, b: "untitled"), транспортер понимает "untitled" как константа, а не как строка.Следовательно, b будет иметь тип "untitled", поэтому T будет иметь тип "untitled".Поскольку вы используете a типа string, компилятор не может привести string к "untitled".

Решение уже предоставлено @ Titian Cernicova-Dragomir answer

0 голосов
/ 26 ноября 2018

Вы объявили deflt как универсальную функцию, но использовали ее как обычную функцию

const deflt = <T>(val: (T | undefined | null), defaultVal: T): T => {
    if (val === undefined || val === null) {
      return defaultVal;
    }
    return val;
}

function maybeLabelName(name?: string) {
    return deflt<typeof name>(name, 'untitled');
}
0 голосов
/ 26 ноября 2018

Я думаю, что это немного странно, когда машинопись выводит T в этом случае.Поскольку вы указываете константу 'untitled', компилятор выведет T в виде строкового литерала типа 'untitled', поскольку это самый простой сайт для вывода T.Затем он проверит другой параметр по типу строкового литерала и обнаружит, что string нельзя присвоить 'untitled'.Обходным путем будет уменьшение приоритета второго параметра при выводе T путем добавления дополнительного пересечения с {}:

export const deflt = <T>(val: (T | undefined | null), defaultVal: T & {} ): T => {
    if (val === undefined || val === null) {
        return defaultVal;
    }
    return val;
}

function maybeLabelName(name: string | undefined) {
    return deflt(name, 'untitled'); // T is string now
}

Другое решение (если вы не можете изменить исходную функцию)было бы явно заявить untitled к string, что в основном и было тем, что вы уже пробовали.

function maybeLabelName(name: string | undefined) {
    return deflt(name, 'untitled' as string); // T is string now
}
...