Here is a sample JavaScript code:
/**
* Generates the sequence of numbers.
*
* @param {number} i - The first number.
* @yields {number} The next number.
*/
function* gen(i) {
while (true) {
yield i ;
}
}
const g = gen(1);
// 1st case
// No error here
const n = g.next();
if (!n.done) {
const x = n.value * 2;
console.log(x);
}
// 2nd case
// Error:
// The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
// Other variants of the error for other expressions:
// Type 'number | void' is not assignable to type 'number'.
// Type 'void' is not assignable to type 'number'
const y = g.next().value * 2;
console.log(y)
gen
function generates an infinte sequence of numbers. So I don't need to check whether it's finished.
Is it possible to remove the typecheck error in the 2nd case? Here is a similar question: How to avoid void type in generators Typescript. The following suggestions was given:
- check first if done is true and act accordingly (early return, throw, whatever you need);
- if you know that the iterator will always return a value you can use a non-null assertion.
But I don't want to check done
. And I can't add a non-null assertion, because it's JavaScript, not TypeScript. Could you suggest how to remove the error?
Here is jsconfig.json
:
{
"compilerOptions": {
"lib": ["es2021"],
"allowJs": true,
"checkJs": true,
"noEmit": true,
"module": "es2022",
"target": "es2021",
"strict": true,
"strictPropertyInitialization": false,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"importsNotUsedAsValues": "error"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
CodePudding user response:
TypeScript is protecting you from g.return()
. There does not exist a generator function which can never be done
. The Generator.prototype.return()
method can even be implicitly called when using generator objects in for...of
loops:
function* gen(i) {
while (true) {
yield i ;
}
}
const g = gen(1);
for (const n of g) {
if (n > 5) break;
console.log(n);
}
console.log(g.next());
CodePudding user response:
I don't think this is a problem with Typescript, since it is supposed to catch potential code errors like this.
If you're absolutely certain that the generator will not return a null value, you could explicitly write out the type like so:
const y = (g.next().value as number) * 2;