Тип возврата для универсального вывода из интерфейса - PullRequest
0 голосов
/ 26 сентября 2019

Я описываю все доступные методы для интерфейса с помощью строкового литерального типа объединения.
Затем это используется для описания интерфейса.

Затем я определяю тип возврата любого данного метода из этого интерфейса., который всегда должен быть boolean.

Каким-то образом TypeScript думает, что это не всегда логическое значение, но я не понимаю, почему и как изменить типизацию, чтобы выразить более четко, что я хочу.

export type method = 'add' | 'get';

export type intfce = { [M in method]: () => boolean };
// => { add: () => boolean; get: () => boolean; }

export type ret<M extends method> = ReturnType<intfce[M]>;
export type retAdd = ret<'add'>;  // => boolean
export type retGet = ret<'get'>;  // => boolean

export function fn<M extends method>(): ret<M> {
  return true;  // Error: Type 'true' is not assignable to type 'ReturnType<intfce[M]>'.
}
export function fn2(): boolean {
  return true;  // OK
}

Я много искал ответы, но, кажется, трудно точно описать, что я пытаюсь сделать, и найти ответ на него.

Мое лучшее предположение, что в случае function fn<M extends method> M может быть больше, чем просто 'add' | 'get'.
Итак, я попробовал:

const resAdd = fn<'add'>(); // OK
const resGet = fn<'get'>(); // OK
const resPut = fn<'put'>(); // Error: Type '"put"' does not satisfy the constraint 'method'.
const resToString = fn<'toString'>(); // Error: Type '"toString"' does not satisfy the constraint 'method'.
const resEmpty = fn<''>(); // Error: Type '""' does not satisfy the constraint 'method'.
const resNull = fn<null>(); // Error: Type 'null' does not satisfy the constraint 'method'.
const resUndefined = fn<undefined>(); // Error: Type 'undefined' does not satisfy the constraint 'method'.
const resNumber = fn<0>();  // Error: Type '0' does not satisfy the constraint 'method'.
const resObj = fn<{}>();  // Error: Type '{}' does not satisfy the constraint 'method'.

Полученные ошибки указывают на то, что только 'add' | 'get' действительно возможны, что возвращает меня к квадрату 1...


Я пытался, если ReturnType является виновником, и это действительно так, так как код ниже не содержит ошибок:

export type intfce2 = { [M in method]: boolean };
export type ret2<M extends method> = intfce2[M];
export type retAdd2 = ret2<'add'>;  // => boolean
export type retGet2 = ret2<'get'>;  // => boolean

export function fn3<M extends method>(): ret2<M> {
  return true;  // Error: Type 'true' is not assignable to type 'ReturnType<intfce[M]>'.
}

Каким может быть ReturnType (повторно-) определено, чтобы заставить работать исходный код?

...