openlang

Контракт вызываемой функции в Typescript

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

  interface ITextRenderer {
      (text: string, capitalize : boolean): string;
  };

  //No compiler diagnostic at this assignment.
  var capitalRenderer: ITextRenderer = function (text: string) {
      return text.capitalizeCase();
  }  

  capitalRenderer("demo"); //A diagnostic occurs at this call instead.
Переведено с английскогоПоказать оригинал

Разговор продолжается 2

Следуя доводам
  1. Ссылка на ответ

    Интерфейс требует, чтобы каждый вызывающий реализующую его функцию передавал оба обязательных аргумента, text и capitalize.

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

    Почему это допустимо? Так можно заменить одну реализацию другой без изменения вызывающего кода.

    Например: Обе реализации ITextRenderer ниже можно подставить, и код продолжит работать.

      interface ITextRenderer {
          (text: string, capitalize: boolean): string;
      };
    
      var capitalRenderer: ITextRenderer = function (text: string) {
          return text.capitalizeCase();
      }
    
      var flexibleRenderer: ITextRenderer = function (text: string, capitalize: boolean) {
          if (capitalize) {
              return text.capitalizeCase();
          }
    
          return text.toLowerCase();
      }
    
      // Either implementation can go here
      //var renderer = capitalRenderer;
      var renderer = flexibleRenderer;
    
      renderer("demo", true);

    Без такого разрешения в TypeScript функции capitalRenderer понадобился бы параметр capitalize, хотя тело вообще его не использует, а это ухудшает читаемость функции.

    Переведено с английскогоПоказать оригинал
  2. Ссылка на ответ

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

    Чтобы проверка типов принимала варианты с разным количеством аргументов, объявите эти альтернативы явно как перегрузки, например

      interface ITextRenderer {
          (text: string, capitalize: boolean): string;
          (text: string): string;
      };
    
      var capitalRenderer: ITextRenderer = function (text: string) {
          return text.capitalizeCase();
      }  
    
      capitalRenderer("demo"); // selects the single-parameter signature
      capitalRenderer("demo","false"); // selects the double-parameter signature

    При этом остаётся без ответа вопрос, почему TypeScript проверяет функцию по-разному при определении и при вызове. Без официальной документации с объяснением можно предположить технические ограничения из-за реализации TypeScript на TypeScript / JavaScript и посмотреть, изменится ли это, когда TypeScript 7 будет реализован на Go: https://github.com/microsoft/typescript-go?tab=readme-ov-file#typescript-7

    Переведено с английскогоПоказать оригинал

Другие стороны того же вопроса

  1. Инициализация TypeScript Map со значениями в виде массивов строк

    Создаю Map, в котором каждая запись содержит массив строк. Как одновременно задать его тип и инициализировать одним выражение…

    Ответы 2Последняя активность typescript
  2. Ошибка преобразования типа address в uint256 в Solidity

    Я создал массив структур и попытался получить из него значения каждого аккаунта. Но передача переменной address, содержащей m…

    Ответы 3Последняя активность solidity
  3. List<Int> только для чтения - это снимок?

    List<Int> всего лишь представление только для чтения, а не снимок. Он сообщает потребителю, какие операции доступны через эту…

    Ответы 4Последняя активность kotlin