Repository navigation
Closed
Labels
BugA bug in TypeScriptA bug in TypeScriptFixedA PR has been merged for this issueA PR has been merged for this issueRescheduledThis issue was previously scheduled to an earlier milestoneThis issue was previously scheduled to an earlier milestone
Milestone
Description
TypeScript 3.7.2
Playground link
Compiler Options:
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"useDefineForClassFields": false,
"alwaysStrict": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"downlevelIteration": false,
"noEmitHelpers": false,
"noLib": false,
"noStrictGenericChecks": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"esModuleInterop": true,
"preserveConstEnums": false,
"removeComments": false,
"skipLibCheck": false,
"checkJs": false,
"allowJs": false,
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"target": "ES2017",
"module": "ESNext"
}
}Input:
const message: string = 'hello world';
console.log(message);
const b = message ? message : undefined;
const c = message ? message : undefined;
const a: [string, undefined] | [undefined, string] | [string, string] | [undefined, string] = [b, c];Output:
"use strict";
const message = 'hello world';
console.log(message);
const b = message ? message : undefined;
const c = message ? message : undefined;
const a = [b, c];Expected behavior:
To me, Type [string | undefined, string | undefined] is assignable to type [string, undefined] | [undefined, string] | [string, string] | [undefined, undefined].
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFixedA PR has been merged for this issueA PR has been merged for this issueRescheduledThis issue was previously scheduled to an earlier milestoneThis issue was previously scheduled to an earlier milestone
Activity
AnyhowStep commentedon Nov 7, 2019
Except, it isn't.
jack-williams commentedon Nov 7, 2019
This feels like a bug. As per this comment, recent changes to discriminant assignment should probably handle this. For example, this works:
AnyhowStep commentedon Nov 7, 2019
Sounds like a bad idea to allow the assignment, since it's unsound.
Somewhat related to #33205
I keep telling everyone assignments like these aren't sound and shouldn't be allowed but it's like I'm talking to the wind >.>
And everyone just goes on like I haven't said anything
jack-williams commentedon Nov 7, 2019
TypeScript has always allowed covariant references, much like many other languages, which are known to be unsound in the presence of mutation and aliasing.
AnyhowStep commentedon Nov 7, 2019
Except, in this case, it's a contravariant assigment, isn't it?
We're trying to assign
string|undefinedtostring, orstring|undefinedtoundefinedPlayground
Also related,
Playground
jack-williams commentedon Nov 7, 2019
It's covariant:
[string | undefined, string | undefined]is a subtype of[string, undefined] | [undefined, string] | [string, string] | [undefined, undefined]because the set of values denoted by the former are a subset of the values denoted by the latter.Syntax directed subtyping algorithms commonly suffer from the problem that they can't prove this relation using the normal decomposition rules, exactly because you decompose into things that try to related
string | undefinedtostring.AnyhowStep commentedon Nov 7, 2019
If mutations are disallowed, I agree with you about the former being a subset of the latter.
If mutations are allowed, then I disagree.
But I guess TS pretends mutations don't happen.
Given a value
xof type[string|undefined, string|undefined], you can always change the value ofx[0]to astring, or change it toundefined.But,
yof type[string, undefined], you cannot changey[0]toundefined.yof type[undefined, string], you cannot changey[0]tostring.yof type[string, string], you cannot changey[0]toundefined.yof type[undefined, undefined], you cannot changey[0]tostring.So, I probably should not consider mutations, since TS pretends they don't happen (in general), but it's hard for me to do so =x
RyanCavanaugh commentedon Nov 8, 2019
Ron Buckton (@rbuckton) n.b. there's a typo (missing the
[undefined, undefined]case in the OP) but this looks like a case that should have been handled by your PR to look for matching unionsrbuckton commentedon Dec 16, 2020
It looks like this was fixed by #39393, and has been working since 4.0.