type deduce error
Closed this issue ยท 7 comments
๐ Search Terms
type deduce
๐ Version & Regression Information
all version
โฏ Playground Link
No response
๐ป Code
const num = (): number => {
return 10;
};
const numAndObj = (arg: number) => {
if (arg) {
return arg;
} else {
return {
name: "test",
age: 10,
};
}
};
const numOrObj = num() ?? numAndObj(10);
const numOrObj2 = num() || numAndObj(10);
const test = (num: number) => {};
test(numOrObj);
test(numOrObj2);๐ Actual behavior
tsc test.ts
test.ts:22:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
22 test(numOrObj2);
~~~~~~~~~
Found 1 error in test.ts:22
๐ Expected behavior
tsc --noEmit test.ts
test.ts:21:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
21 test(numOrObj);
~~~~~~~~
test.ts:22:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
22 test(numOrObj2);
~~~~~~~~~
Found 2 errors in the same file, starting at: test.ts:21
Additional information about the issue
type of numOrObj is deduce error
in vscode:

This is working as intended.
The type of numOrObj is number, because the coalesce operator ?? only uses the right-hand expression when the left-hand one is null or undefined, but according to the return type definition of num() this can never be the case.
But with numOrObj you use the logical-or operator ||, which uses the right-hand expression when the left-hand one is falsy. The return type definition says it can return number, and the number 0 is falsy, so the right-hand expression might be used. At this point the compiler doesn't know that according to the implementation of num() the return value is always truthy. For this to work the compiler would need to be able to declare the return type as "number except 0", but this would require "Negated Types" (#4196) first.
when use tsc to check test.ts file, that got a error:
tsc --noEmit test.ts
test.ts:21:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
21 test(numOrObj);
> This is working as intended.
>
> The type of `numOrObj` is `number`, because the coalesce operator `??` only uses the right-hand expression when the left-hand one is `null` or `undefined`, but according to the return type definition of `num()` this can **never** be the case.
>
> But with `numOrObj` you use the logical-or operator `||`, which uses the right-hand expression when the left-hand one is _falsy_. The return type definition says it can return `number`, and the number `0` is falsy, so the right-hand expression **might** be used. At this point the compiler doesn't know that according to the implementation of `num()` the return value is **always** truthy. For this to work the compiler would need to be able to declare the return type as "number except 0", but this would require "Negated Types" ([#4196](https://github.com/microsoft/TypeScript/issues/4196)) first.
Yes, that error is correct.
๐ค This is an automated response. I looked for things that might help (duplicates, FAQ entries, etc) but didn't find anything. A human will take a look!
Yes, that error is correct.
I think that is incorrect, because when use:
// not specify file
tsc --noEmit
test.ts:22:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
22 test(numOrObj2);
// specify file:
tsc --noEmit test.ts
test.ts:21:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
21 test(numOrObj);
test.ts:22:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
22 test(numOrObj2);
Found 2 errors in the same file, starting at: test.ts:21
for the same file, different results.
and when compile test.ts:
tsc test.ts
test.ts:21:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
21 test(numOrObj);
~~~~~~~~
test.ts:22:6 - error TS2345: Argument of type 'number | { name: string; age: number; }' is not assignable to parameter of type 'number'.
Type '{ name: string; age: number; }' is not assignable to type 'number'.
22 test(numOrObj2);
~~~~~~~~~
Found 2 errors in the same file, starting at: test.ts:21
the numOrObj type is 'number | {name:string, age: number}', is not a number
When you specify the files then your local tsproject.json is not used, so you likely compile with different settings (e.g. strict is turned off by default).
When you specify the files then your local tsproject.json is not used, so you likely compile with different settings (e.g. strict is turned off by default).
thanks very much for you answer