如何指定无限生成器的类型?



下面是一个JavaScript示例代码:

/**
* 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函数生成一个无穷数列。所以我不需要检查它是否完成了。

是否可以在第二种情况下删除类型检查错误?这里有一个类似的问题:如何在Typescript生成器中避免void类型。建议如下:

  1. 首先检查done是否为真,并采取相应的行动(提前返回,抛出,无论你需要什么);
  2. 如果你知道迭代器总是返回一个值,你可以使用非空断言。

但是我不想检查done。我不能添加非空断言,因为这是JavaScript,不是TypeScript。你能建议如何消除这个错误吗?

这里是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"]
}

TypeScript是保护你免受g.return()。不存在永远不能为done的生成器函数。在for...of循环中使用生成器对象时,甚至可以隐式调用Generator.prototype.return()方法:

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());

我不认为这是Typescript的问题,因为它应该捕捉像这样的潜在代码错误。

如果你绝对确定生成器不会返回空值,你可以显式地写出该类型,如下所示:const y = (g.next().value as number) * 2;

最新更新