英文:
TypeScript Heisenbug driving me crazy: Excluding types with control statements
问题
I simplified an error I was getting to a base case that sometimes reproduces on the TypeScript Playground, but usually it needs to be poked to be reproduced. It fails every time for me locally when running tsc
.
type Result = {
success: true,
value: string,
} | {
success: false,
error: string,
};
const x = {success: true, value: 'hello'} as Result;
if (!x.success) {
console.log(x.error);
}
If you don't see an error on TypeScript Playground, click [TS Config] > and change Target. It doesn't seem to matter what I change it to. Change it to "ES2017" or "ES2019". This seems to trigger the error for me.
Questions:
(1) Is there something wrong with the approach in the code or should TypeScript be handling it?
(2) Is there a decent workaround (short of casting directly everywhere)?
英文:
I simplified an error I was getting to a base case that sometimes reproduces on the TypeScript Playground, but usually it needs to be poked to be reproduced. It fails every time for me locally when running tsc
.
type Result = {
success: true,
value: string,
} | {
success: false,
error: string,
};
const x = {success: true, value: 'hello'} as Result;
if (!x.success) {
console.log(x.error);
}
If you don't see an error on TypeScript Playground, click [TS Config] > and change Target. It doesn't seem to matter what I change it to. Change it to "ES2017" or "ES2019". This seems to trigger the error for me.
Questions:
(1) Is there something wrong with the approach in the code or should TypeScript be handling it?
(2) Is there a decent workaround (short of casting directly everywhere)?
答案1
得分: 3
TypeScript 似乎不能正确地基于 !
操作符进行缩小范围。如果您直接与联合类型的值进行比较,它可以正常工作 (playground 链接):
type Result = {
success: true,
value: string,
} | {
success: false,
error: string,
};
const x = {success: true, value: 'hello'} as Result;
if (x.success === false) {
console.log(x.error);
}
这让我感到惊讶,基于不一致的结果,值得考虑提交一个 TypeScript 存储库问题。
英文:
TypeScript does not appear to be properly narrowing based off of the !
operator. If you do a direct comparison against the value from your union, it works (playground link):
type Result = {
success: true,
value: string,
} | {
success: false,
error: string,
};
const x = {success: true, value: 'hello'} as Result;
if (x.success === false) {
console.log(x.error);
}
This is surprising to me, and, based on the inconsistent results, it may be worth filing a TypeScript repo issue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论