TypeScript: вернуть тот же тип, что и параметр

formatISODate функция ожидает строковое значение.

Есть много строк, которые мне нужно преобразовать, если они не определены. Я мог сделать следующее:

{
  date1: date1 ? formatISODate(date1) : undefined,
  date2: date2 ? formatISODate(date2) : undefined
  ...
}

Чтобы не повторять одно и то же троичное выражение, я написал функцию ниже.

function convertDate<T extends string | undefined>(isoDate?: string): T {
  return isoDate ? formatISODate(isoDate) : undefined;
}

Но у него есть ошибка типа.

Ошибка: 'undefined' можно присвоить ограничению типа 'T', но 'T' может быть создан с другим подтипом ограничения 'строка | undefined ».

Можно ли решить проблему типа для этого варианта использования?


person kk-dev11    schedule 16.08.2019    source источник
comment
есть ли у formatISODate параметр типа? Если нет, то я не уверен, что вам дает Т. Эта функция должна просто вернуть возвращаемое значение formatISODate | неопределенный   -  person Reid Evans    schedule 16.08.2019
comment
formatISODate имеет тип, а именно ожидает строку и возвращает строку. return string | undefined покажет ошибку типа при использовании date1: convertDate(date1), если date1 строго является строкой.   -  person kk-dev11    schedule 16.08.2019
comment
Я неправильно прочитал ранее. Просто введите его как convertDate (isoDate ?: string): string. Это должно сработать, если в вашем tsconfig не включены строгие проверки на null (в чем я сомневаюсь, что вы делаете, учитывая, что ваш встроенный тернар, кажется, работает)   -  person Reid Evans    schedule 16.08.2019


Ответы (1)


Сделаем пример еще проще.

function convertDate<T extends string | undefined>(isoDate?: string): T {
   return undefined
}

'undefined' присваивается ограничению типа 'T'

Означает: то, что вы возвращаете в функции (undefined), соответствует ограничениям вашего параметра универсального типа T (extends string | undefined).

, но 'T' может быть создан с другим подтипом ограничения 'string | неопределенный'.

Значит: TypeScript не считает это безопасным. Что делать, если вы определили свою функцию таким образом во время компиляции:

// expects string return type according to generics
// but you return undefined in function body
const res = convertDate<string>("2019-08-16T16:48:33Z")

Затем в соответствии с вашей подписью вы ожидаете, что тип возврата будет строковым. Но во время выполнения это не так! Это несоответствие в том, что T может быть создан с другим подтипом (здесь string), чем вы возвращаете в функции (undefined), выражается в ошибке TypeScript.

Возможные решения:

Единственный способ убедить компилятор - жестко привести тип возвращаемого значения:

declare function formatISODate(d: string): string

function convertDate<T extends string | undefined>(isoDate?: string): T {
  return (isoDate ? formatISODate(isoDate) : undefined) as T
}

Но я не уверен, действительно ли вы этого хотите. Параметр универсального типа довольно бесполезен в том виде, как вы определяете его в своей функции, поскольку он не используется в ваших параметрах. Почему бы просто не написать

function convertDate(isoDate?: string): string | undefined {
  return isoDate ? formatISODate(isoDate) : undefined;
}

Если ваша цель - просто избежать повторения одного и того же троичного выражения, вы можете добиться этого с помощью приведенного выше кода.

person ford04    schedule 16.08.2019
comment
Большое спасибо за подробное объяснение, почему это может не получиться. Вы правы, что параметр универсального типа в данном случае не имеет смысла. - person kk-dev11; 25.08.2019