Несколько типов возврата TypeScript с идентичными параметрами

Фон

Пытаясь проникнуться духом TypeScript, я пишу полностью типизированные подписи в своих компонентах и ​​службах, что распространяется на мои пользовательские функции проверки для форм angular2.

Я знаю, что я могу перегрузить подпись функции, но для этого необходимо, чтобы параметры были отличается для каждого типа возврата, потому что tsc компилирует каждую подпись в отдельную функцию:

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any { /*common logic*/ };

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

private active(): Promise<void|null> { ... }

Однако в контексте валидаторов настраиваемой формы angular2 одна подпись (один параметр типа FormControl) может возвращать два разных типа: Object с ошибками формы или null, чтобы указать, что элемент управления не содержит ошибок.

Это, очевидно, не работает:

private lowercaseValidator(c: FormControl): null;
private lowercaseValidator(c: FormControl): Object {
    return /[a-z]/g.test(c.value) ? null : { lowercase: this.validationMessages.lowercase };
}

И не делаю

private lowercaseValidator(c: FormControl): null|Object {...}
private lowercaseValidator(c: FormControl): <null|Object> {...}

(Интересно, что я получаю следующие ошибки, а не что-то более информативное:

error TS1110: Type expected.
error TS1005: ':' expected.
error TS1005: ',' expected.
error TS1128: Declaration or statement expected.

)

TL;DR

Я просто использую

private lowercaseValidator(c: FormControl): any { ... }

что, казалось бы, сводит на нет преимущество наличия сигнатур типов?

В общем, с нетерпением жду ES6

Хотя этот вопрос вдохновлен валидаторами форм angular2, которые обрабатываются непосредственно фреймворком, поэтому вы можете не заботиться об объявлении возвращаемого типа, он по-прежнему применим, особенно с учетом таких конструкций ES6, как function (a, b, ...others) {}

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

использованная литература


person msanford    schedule 25.10.2016    source источник
comment
Зачем тебе там ноль? Это не отдельный тип, и Object может иметь значение null.   -  person Sami Kuhmonen    schedule 25.10.2016
comment
(1) Не используйте Object, используйте вместо этого any. (2) Это: private lowercaseValidator(c: FormControl): null|Object {...} должно работать.   -  person Nitzan Tomer    schedule 25.10.2016
comment
null | Object, похоже, работает на игровая площадка   -  person Sean Vieira    schedule 25.10.2016
comment
@SamiKuhmonen Kickself: Я не учел этого. Думаю, я слишком много думаю о конкретной необходимости подкрепить тот факт, что он ничего не вернет или что-то в этом роде. Тем не менее, средняя часть вопроса все еще (возможно) применима.   -  person msanford    schedule 25.10.2016
comment
@NitzanTomer Это определенно вариант, но если я собираюсь это сделать, зачем вообще указывать объявление типа? Вы слишком много утверждаете, просто не беспокойтесь, это может быть разумным ответом :)   -  person msanford    schedule 25.10.2016
comment
Я не это имел в виду, использование Object почти похоже на использование any, но: Тип any - это мощный способ работы с существующим JavaScript, позволяющий постепенно включать и отключать проверку типов во время компиляции. Вы можете ожидать, что Object будет играть ту же роль, что и на других языках. Но переменные типа Object позволяют вам присваивать им любое значение - вы не можете вызывать для них произвольные методы, даже те, которые действительно существуют (typescriptlang.org/docs/handbook/basic-types.html#any)   -  person Nitzan Tomer    schedule 25.10.2016
comment
@NitzanTomer Спасибо за разъяснения!   -  person msanford    schedule 25.10.2016


Ответы (2)


Хорошо, это правильный путь, если вы хотите иметь правильные типы:

type CustomType = { lowercase: TypeOfTheProperty };
// Sorry I cannot deduce type of this.validationMessages.lowercase,
// I would have to see the whole class. I guess it's something
// like Array<string> or string, but I'm not Angular guy, just guessing.

private lowercaseValidator(c: FormControl): CustomType | null {
    return /[a-z]/g.test(c.value) ? null : { lowercase: this.validationMessages.lowercase };
}

Более общий пример

type CustomType = { lowercase: Array<string> };

class A {
      private obj: Array<string>;

      constructor() {
            this.obj = Array<string>();
            this.obj.push("apple");
            this.obj.push("bread");
      }

      public testMethod(b: boolean): CustomType | null {
            return b ? null : { lowercase: this.obj };
      }
}

let a = new A();
let customObj: CustomType | null = a.testMethod(false);
// If you're using strictNullChecks, you must write both CustomType and null
// If you're not CustomType is sufficiant
person Erik Cupal    schedule 21.11.2016
comment
У меня проблема с использованием метода, который возвращает несколько типов. Если у меня есть собственный метод, который возвращает CustomType1 следующим образом: mymethod(): CustomType1 { return someMethodThatReturnsCustomType1AndNull(); }, я получаю сообщение об ошибке. Как это исправить? - person HisDivineShadow; 22.03.2020
comment
Предпочтительно использовать interface вместо type, если вам действительно не нужно использовать тип. - person Josh Habdas; 22.02.2021

Чтобы добавить к ответу Эрика. В последней строке его второго примера вместо повторного объявления типа вы можете использовать ключевое слово as.

let customObj = a.testMethod(false) as CustomType;

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

type Person = { name: string; age: number | string };

const employees: Person[] = [
  { name: "John", age: 42},
  { name: "April", age: "N/A" }
];

const canTakeAlcohol = employees.filter(emp => {
  (emp.age as number) > 21;
});
person Shonubi Korede    schedule 04.09.2020