Typescript: функция-обертка предотвращает вывод анонимной функции - PullRequest
0 голосов
/ 16 ноября 2018

Я сталкиваюсь с неприятностями при наборе текста:

function identity<T>(v: T): T{ return v; }

function execute(fn: {(n: number):string}) {}

execute((n) => {
    // type of n is 'number'
    return n.toFixed();
})

execute(identity((n) => {
    // type of n is 'any'
    return n.toFixed();
}))

Когда типизированная функция высшего порядка execute получает функцию, аргументы этой анонимной функции вводятся с помощью логического вывода. Однако передача этой анонимной функции в функцию-оболочку identity приводит к потере этих предполагаемых типов. Могу ли я внести какие-либо корректировки в конструкцию execute или identity, которая позволит этим выводам все еще выводиться?

ПРИМЕЧАНИЕ Для простоты identity здесь является чистой функцией. На практике это не так, но должно иметь такую ​​же типизацию, как эта identity функция. См. checkpoint в контексте вопроса для более подробной информации.

см. На игровой площадке TS


Context

Это общая форма проблемы, с которой я столкнулся при загрузке данных в контексте жизненного цикла компонента React. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Не следует вызывать setState для компонента, который больше не монтируется, я предотвращаю срабатывание обратного вызова загрузки.

function loadData():Promise<MyDataType> {/*...*/}    

// Wraps the passed function (handleDataLoaded), 
// such that when the returned function is executed the 
// passed function is conditionally executed depending 
// on closure state.
function checkpoint(fn){/*...*/}

// Add data to the state of the component
function handleDataLoaded(val: MyDataType){/*...*/}



// react lifecycle hook componentDidMount
    loadData()
        .then(checkpoint(handleDataLoaded));

// react lifecycle hook componentWillUnmount 
// adjusts state of checkpoint's closure such that handleDataloaded
// is not fired after componentWillUnmount

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Нет абсолютно никаких неприятностей.Это больше похоже на то, что вы испытываете какую-то ошибку в своей логике (в своем уме).Неиспользование строгого режима - еще одна проблема.

/* execute( */  identity((n) => {
    // type of n is 'any', why wouldn't it be?
    // There is no type constraint in `identity` function, 
    // hence you have absolutely no reason to expect `n` to have type `number` 
    // I commented out the wrapping by `execute` function 
    // so that it doesn't confuse you. Because, no matter
    // if it's there or not, you should first figure out
    // the shape and type of underlying expression,
    // because this is how Typescript figures them out.
    return n.toFixed();
}) /* ) */

Однако

function identity<T extends {(n: number): string}>(v: T): T{ return v; }

/* execute( */ identity((n) => {
    // type of n is 'number', because we added a constraint to the type parameter `T` in `identity` function
    return n.toFixed();
}) /* ) */ 

Вы также можете сделать это:

/* execute( */ identity<{(n: number): string}>((n) => {
    // type of n is 'number'
    return n.toFixed();
}) /* ) */

И

execute(identity((n: string) => {
    // this is a TS error
    // "Argument of type '(n: string) => () => string' is not 
    // assignable to parameter of type '(n: number) => string'"
    return n.toFixed;
}))

Наконец, вы должны всегда использовать строгий режим (добавьте "strict": true в "compilerOptions" файла tsconfig.json), и вы никогда не будете испытывать такие предостережения.

0 голосов
/ 16 ноября 2018

То, что вы написали, фактически совпадает с:

function identity<T>(v: T): T{ return v; }

function execute(fn: {(n: number):string}) {}

execute((n) => {
    // type of n is 'number'
    return n.toFixed();
})

var func = identity((n) => {
    // type of n is 'any'
    return n.toFixed();
});
execute(func);

Нет, если вы явно указали универсальный параметр:

var func = identity<number>((n) => {
    // type of n is 'any'
    return n.toFixed();
});

Вы получите ошибку компилятора:

enter image description here

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

Если вы объясните, что вы пытаетесь сделать, мы можемможет предоставить вам разрешение.

...