Difference when importing from a JS an unknown value
Closed this issue · 2 comments
Steps to reproduce
// test2.js
import { List } from 'immutable';
export function fnJS(longId) {
return longId;
}
// eslint-disable-next-line import/no-mutable-exports
export function getVarJS() {
return List().first();
}// test.ts
import { List } from 'immutable';
import { fnJS, getVarJS } from './test2';
function fnTS(longId: string): string {
return longId;
}
export function getVarTS() {
return List().first();
}
fnTS(getVarTS());
fnTS(getVarJS());
fnJS(getVarTS());
fnJS(getVarJS());The type of List().first() is the following:
interface List<V> {
first(): V | undefined;
}Behavior with typescript@5.8
src/test.ts:12:6 - error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'string'.
12 fnTS(getVarTS());
~~~~~~~~~~
Found 1 error in src/test.ts:12
Behavior with tsgo
src/test.ts:12:6 - error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'string'.
12 fnTS(getVarTS());
~~~~~~~~~~
src/test.ts:13:6 - error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'string'.
13 fnTS(getVarJS());
~~~~~~~~~~
Found 2 errors in the same file, starting at: src/test.ts:12
Possible explanation
It seems that by passing in the JS file, the return type is marked as any in TS5.8, but in TSgo it is marked as unknown.
I'm reporting this as a difference, but I'm totally OK if you consider this a breaking change.
For the record, If I force an unknown parameter, both function call throws an error:
let v: unknown;
fnTS(v);
fnTS(v);returns:
src/test.ts:18:6 - error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'string'.
18 fnTS(v);
~
src/test.ts:19:6 - error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'string'.
19 fnTS(v);
~
This is intentional. A while ago, TypeScript changed the default constraint to unknown, but we didn't change JS. In the new code, this difference has been removed, such that the same code pasted from JS behaves the same in TS. For example: Playground Link
If you want to instantiate it as any, you should annotate it as such.
OK. Looks good to me. The final purpose is to migrate to TS in the end 😉
I reported because it's different than the actual.