I am working on a project with typescript & next.js, and for some reason types for function arguments are not being checked.
I have provided a code sample below, for which I expect the function call to complain about me providing a string
instead of an SExpr
.
abstract class SExpr { abstract toString(): string } function parse(expr: SExpr) { // ... } parse('123') // does not complain - compiles just fine
I have never experienced such an issue before, and have tried my best to find an option to change in tsconfig.json
to resolve this issue, but unfortunately have not been able to fix it.
At this point I suspect that next.js might be overriding my tsconfig.json
or the like, as I’ve never had any problems when just using typescript.
My tsconfig.json
is as follows:
{ "compilerOptions": { "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "baseUrl": ".", "noImplicitAny": true, "allowJs": true, "skipLibCheck": true, "alwaysStrict": true, }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] }
Advertisement
Answer
This is by design.
TypeScript has a structural type system not a nominal one. In the structural type system, A
is a subtype of B
if all the members of B
are provided by A
. The heritage, of A
is not a determining factor.
In your case SExpr
has only one member, a toString
method that takes no parameters and returns a string
, and all JavaScript objects provide such a member, including strings
.
In sum, TypeScript is behaving as intended and you should consider a different approach, such as employing Discriminated Unions, instead of class hierarchies to represent the types of the various kinds of expressions your program parses.