Почему я должен указывать имя переменной в типе возвращаемого значения TS generi c? - PullRequest
0 голосов
/ 07 февраля 2020

Я использую машинописный текст для написания некоторой функции, и TS принимает ее:

export const useSomething = <T>() => {
    const useStorage = <T>(key: string, initialData: T) : [T, (newData: T) => Promise<void>] => {
        const [data, setState] = useState<T>(initialData);
        const setData = async(newData: T) : Promise<void> => {
            await storage.setItem<T>(key, newData);
        };
        return [data, setData];
    }
};

Но изначально я хотел написать тип возврата useStorage таким образом:

[T, (T) => Promise<void>]

Почему TypeScript хочет, чтобы я записал имя newData до появления T?

Ответы [ 2 ]

4 голосов
/ 07 февраля 2020

Я думаю, что на канонический ответ, на который вы можете надеяться, можно найти ответы на вопросы GitHub microsoft / TypeScript # 13152 и microsoft / TypeScript # 3081 . Суть ситуации такова:

Поддержка имен параметров в типах функций полезна в качестве документации для функций и методов в библиотеках. Тип функции (username: string, password: string) => void совпадает с типом (arg0: string, arg1: string) => void, но первый, вероятно, помогает разработчикам писать код больше, чем второй. Таким образом, поддержка аннотированных имен параметров в типах функций предусмотрена, задокументирована в (все более устаревшей) TypeScript spe c и используется повсеместно в библиотеках. По словам одного из сопровождающих языка :

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


Кроме того, где аннотации типов для именованных значений поддерживаются в TypeScript, типы могут быть опущены , и они будут выведены компилятором. Невозможность сделать что-либо полезное приводит к выводам any. Например, в следующей функции:

function f(x, y): void { }
type F = typeof f;
// type F = (x: any, y: any) => void

тип x и y выводится как any (и вы получаете хорошую ошибку с опцией компилятора --noImplicitAny ). Это аналогично следующей аннотированной версии:

function g(x: any, y: any): void { }
type G = typeof g;
// type G = (x: any, y: any) => void

Применение того же правила к сигнатурам типов f и g приводит к следующему поведению:

type Fprime = (x, y) => void; // --noImplicitAny yells at you here
// type Fprime = (x: any, y: any) => void

type Gprime = (x: any, y: any) => void;
// type Gprime = (x: any, y: any) => void

Поэтому, когда вы пишете (x, y) => void, компилятор интерпретирует x и y как имена , а не как типы . Поскольку тип может быть опущен, имена параметров не могут. Я не думаю, что кому-то это нравится, но так было так долго, что он явно используется в библиотеках , поэтому изменение этого кода нарушило бы реальный код. Из того же комментария, цитируемого выше:

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


Так что это печальный ответ на этот вопрос. Возможно, если бы они могли go назад во времени, они сделали бы так, чтобы имя параметра было необязательным, а тип требовался, чтобы более точно соответствовать нотации теории типов, но сейчас это то, с чем мы застряли.

Надеюсь, это поможет; удачи!

Детская площадка ссылка на код

0 голосов
/ 07 февраля 2020

Ну, вы определяете параметр, а параметры должны иметь имена. Иначе как бы вы к этому относились? Я имею в виду, вы используете newData при звонке setItem. Вы не можете просто использовать setItem(T), это было бы похоже на использование setItem(string), что , скорее всего, не то, что вы хотите. И я говорю «похоже», потому что string является допустимым объектом в JavaScript, и вы можете передать его в качестве параметра. T, однако это может быть любая вещь, возможно, просто определение типа, и эти типы исчезают во время компиляции.

...