Skip to content

Consider resolving of Control flow analysis's confusing with type mismatches in initialization #9886

Closed
@falsandtru

Description

@falsandtru

Adding --strictInitialization new option is helpful to clear behaviors of Control flow analysis.

Problem

CFA is not clear when declaration type and initialization type are not a same type.

class A<T> {
  a: T;
}
class B<T> {
  b: T;
}
function f() {
  var o: A<void> | B<void> = new B<void>();
  if (o instanceof A) return o; // B<void> & A<any>, intended type is A<void>
  // But this operation is a mistake, should be removed.
}

related: #9859

Solution

Disallow initialization by different type.

var o1: A<void> | B<void> = new B<void>(); // error
var o2: A<void> | B<void> = <A<void> | B<void>>new B<void>(); // ok
var o3: A<void> | B<void>;
o3 = new B<void>(); // ok
o3 = new A<void>(); // ok

Activity

yortus

yortus commented on Jul 22, 2016

@yortus
Contributor
var o1: A<void> | B<void> = new B<void>(); // error
...
var o3: A<void> | B<void>;
o3 = new B<void>(); // ok

If assignment at the point of declaration was an error, but the same assignment on the line after the declaration was ok, wouldn't that also be a confusing/unclear behaviour?

falsandtru

falsandtru commented on Jul 22, 2016

@falsandtru
ContributorAuthor

It means

const o1: A<void> | B<void> = new B<void>(); // error
let o3: A<void> | B<void>;
...
o3 = new B<void>(); // ok

Another,

function f(o: A<void> | B<void> = new B<void>()) { // ok
  o = new A<void>(); // ok
}
yortus

yortus commented on Jul 22, 2016

@yortus
Contributor
function f(o: A<void> | B<void> = new B<void>()) {
  o = new A<void>();
}

This currently compiles fine. Are you suggesting it should be an error? If so, how else could you declare a default value for a parameter that had a union type?

falsandtru

falsandtru commented on Jul 22, 2016

@falsandtru
ContributorAuthor

It is a correct case. Updated that example.

yortus

yortus commented on Jul 22, 2016

@yortus
Contributor

So the last line in this example would be an error under this suggestion?

type Optional<T> = Some<T> | None;
interface None { readonly none: string; }
interface Some<T> { readonly some: T; }
const none : None = { none: '' };


class Foo {/***/}
let maybeFoo: Optional<Foo> = none;  // becomes an error?
falsandtru

falsandtru commented on Jul 22, 2016

@falsandtru
ContributorAuthor

Yes, it needs an assertions. You shouldn't modify variables under this suggestion, and should use const instead of let.

let maybeFoo: Optional<Foo> = none;  // error
let maybeFoo: Optional<Foo> = <Optional<Foo>>none;  // ok
yortus

yortus commented on Jul 22, 2016

@yortus
Contributor

you shouldn't modify variables under this suggestion, and should use const instead of let.

This doesn't appear consistent with your original suggestion, which shows an example of a let variable being modified from one type to another (o3), and doesn't use any const variables.

Bear in mind that const variables must have initializers, and your suggestion here is to make it an error to use initializers on union-typed variables.

I'd say it's unclear at best what problem this is solving and what kind of code you are aiming to encourage here. Perhaps you could revise the suggestion to show the kind of use of const variables that you are proposing?

added
DeclinedThe issue was declined as something which matches the TypeScript vision
and removed on Jul 22, 2016
DanielRosenwasser

DanielRosenwasser commented on Jul 22, 2016

@DanielRosenwasser
Member

I really can't come up with a practical case for where this is desirable. I don't know of any situations where I locally want to tell the type system that I don't want it to know the actual type at a given location.

The best thing I can imagine is when you're just trying to experiment with code to see what the apparent members are of a complex type, but in those cases, you can just use the declare keyword to make your declarations ambient.

locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @DanielRosenwasser@yortus@falsandtru@RyanCavanaugh

        Issue actions

          Consider resolving of Control flow analysis's confusing with type mismatches in initialization · Issue #9886 · microsoft/TypeScript