I have JavaScript type checking enabled in my project with the following jsconfig.json
settings:
{
"compilerOptions": {
"target": "ES2020",
"checkJs": true,
"allowJs": true,
"strictNullChecks": false,
"strictFunctionTypes": true,
"module": "NodeNext"
},
"exclude": [
"node_modules",
"**/node_modules/*",
"**/purest/build/*"
]
}
I often have “overloads” that allow multiple types, but either execute slightly differently based on the type, or convert to a uniform type.
Example 1 – conversion to uniform value:
class AccountInfo {
/**
*
* @param {string} accountName
*/
constructor(accountName, someFlag) {
this.accountName = accountName;
this.someFlag = someFlag;
}
}
/**
*
* @param {AccountInfo[]|string[]|string} accountNames
* @returns {boolean}
*/
function createAccounts(accountNames) {
if(typeof accountNames == "string") {
accountNames = [accountNames];
}
for(let i=0; i<accountNames.length; ++i) {
// this prevents an error on assignment
// Argument of type 'string | AccountInfo' is not assignable to parameter of type 'string'.
// Type 'AccountInfo' is not assignable to type 'string'.ts(2345)
// if accountNames[i] the typeof does not translate to it correctly
const acc = accountNames[i];
if(typeof acc == "string") {
accountNames[i] = new AccountInfo(acc, false);
}
}
// perform some operation here where I can know accountNames are always array of account info
/**
*
* @param {AccountInfo} accountInfo
*/
function doWithAccountInfo(accountInfo) {
// do something with account info
}
for(const acc of accountNames) {
// this is underlined because the type checker does not know that acc is always AccountInfo
// Argument of type 'string | AccountInfo' is not assignable to parameter of type 'AccountInfo'.
// Type 'string' is not assignable to type 'AccountInfo'.ts(2345)
doWithAccountInfo(acc);
}
return true;
}
I put the errors I see in the comments. Ideally, I would like to do something like:
/** @type {AccountInfo[]} **/
accountNames;
This should coerce the type to the correct one, or at least it would be convenient, but it does not work – it has no effect on the variable.
I can fix this bu assigning accountNames
to a different variable, but I don’t really want to do runtime changes just to make type system happy.
How to you solve this to get benefits of type checking while keeping the benefits of weak typing?
1