I am learning TypeScript. Just created this simple function and executed it. But I don't understand why does the compiler show the error in the below code. Please refer to the screenshot for the error.
function makePair<T, S> () {
let pair: { first: T, second: S}
function getPair() {
return pair
}
function setPair(x: T, y: S) {
pair = {
first: x, second: y
}
}
return [ getPair, setPair ];
}
const [ getPair, setPair ] = makePair<number, boolean>();
setPair(121, true);
console.log(getPair())
CodePudding user response:
Problem (presumed)
Starting off with a caveat that this is what I presume the problem to be because my understanding of TypeScript isn't extremely deep. This explanation may not be totally correct or may not be elaborated well.
Your function is declared without an explicit return type:
function makePair<T, S> () { ... }
As a result, TypeScript will attempt to infer the return type from the expression returned:
return [ getPair, setPair ];
// ^^^^^^^^^^^^^^^^^^^^
// The expression returned
You may think the expression's type is supposed to be inferred to:
[() => { first: T, second: S }, (x: T, y: S) => void]
However this doesn't happen. It actually got inferred to:
((x: T, y: S) => void)[]
As arrays are mutable, TypeScript cannot guarantee your type will always be [() => { first: T, second: S }, (x: T, y: S) => void]
. It therefore widens the type to ((x: T, y: S) => void)[]
. (Although why it widened it to that, I'm not certain and it could be a bug).
Solution
You'll need to explicitly type your return type. Examples:
function makePair<T, S> (): [() => { first: T, second: S }, (x: T, y: S) => void] {
// ...
return [ getPair, setPair ];
}
function makePair<T, S> () {
// ...
return [ getPair, setPair ] as [typeof getPair, typeof setPair];
}
Or make a const
assertion to force the compiler to not widen types:
function makePair<T, S> () {
// ...
return [ getPair, setPair ] as const;
}
Further reading
- TypeScript documentation on widening
- Related GitHub issue ("Tuples constructed via array literals don't typecheck against tuple constraints")
- Related GitHub issue ("Incorrect type inference when destructuring a tuple")
CodePudding user response:
TypeScript has strict type check features, meaning that if you define some variable of a certain type, it will expect you to pass that type of values only to the variable. Like in your case, while declaring the getPair function in:
const [ getPair, setPair ] = makePair<number, boolean>();
you have declared getPair function of type makePair to expect a number and boolean parameters, which you did not provide while calling it in console.log(getPair())
resulting in it showing error.