Перегруженный тип функции в машинописи - PullRequest
0 голосов
/ 02 сентября 2018

Как создать перегруженный тип функции без предоставления конкретной функции? Изучая тип перегруженной функции, кажется, что можно использовать несколько сигнатур вызовов в интерфейсе / типе объекта:

function a(input: string): string
function a(input: number): number
function a(input: string | number): string | number {
  return input
}

type A = typeof a

type B = {
  (input: string): string
  (input: number): number
}

const b: B = a // Okay!

Определение той же идеи с типом объединения (без этого надоедливого универсального случая, который вам нужен, чтобы перегрузки были счастливы) также работает , типы совместимы в обоих направлениях!

type C = ((input: number) => number) & ((input: string) => string)

const c: C = b // Okay!

const a2: A = c // Okay too!

Но как мне теперь сделать функцию, подходящую для этого типа? Обязательно ли использовать также перегрузку?

const x: A = (input: string | number) => input

и

const y: A = (input: string | number) => {
  if (typeof input === "number") return input
  if (typeof input === "string") return input
  throw "excrement"
}

оба сбоя с одинаковой ошибкой:

Type '(input: string | number) => string | number' is not assignable to type '{ (input: string): string; (input: number): number; }'.
  Type 'string | number' is not assignable to type 'string'.
    Type 'number' is not assignable to type 'string'.

Хуже всего то, что это происходит, даже если я использую менее читаемый тип объединения C

Type '(input: string | number) => string | number' is not assignable to type 'C'.
  Type '(input: string | number) => string | number' is not assignable to type '(input: number) => number'.
    Type 'string | number' is not assignable to type 'number'.
      Type 'string' is not assignable to type 'number'.

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

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

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

0 голосов
/ 02 сентября 2018

Вы можете решить эту проблему, используя универсальное объявление :

type Input = string | number

function a<T extends Input>(input: T): T {
  return input
}

type A = typeof a

type B = {
  (input: string): string
  (input: number): number
}

const b: B = a // Okay!

type C = ((input: number) => number) & ((input: string) => string)

const c: C = b // Okay!

const a2: A = c // Okay too!

Что касается x и y, вы не можете свободно определить тип параметра и ожидать строгого вывода типа вывода. Пропустите определение типов ввода для функций, если вы собираетесь объявить x и y как тип A:

const x: A = input => input

const y: A = input => {
  if (typeof input === "number") return input
  if (typeof input === "string") return input
  throw "excr"
}

Вы можете проверить, что все вышеперечисленное работает в этой демонстрационной версии TypeScript Playground .

...