Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot instantiate a tagged union whose discriminant property is union type #12052

Closed
hellochar opened this issue Nov 4, 2016 · 3 comments · Fixed by #30779
Closed

cannot instantiate a tagged union whose discriminant property is union type #12052

hellochar opened this issue Nov 4, 2016 · 3 comments · Fixed by #30779
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@hellochar
Copy link

Hey typescript, I'm getting an error when instantiating a tagged union whose discriminant property is inlined into the literal, vs. set via assignment right afterwards. Is there something I'm missing here?

TypeScript Version: 2.0.3 (or whatever's on http://www.typescriptlang.org/play/)

Code

interface ILinearAxis { type: "linear"; }

interface ICategoricalAxis { type: "categorical"; }

type IAxis = ILinearAxis | ICategoricalAxis;
type IAxisType = "linear" | "categorical";

function getAxisType(): IAxisType {
    if (1 == 1) {
        return "categorical";
    } else {
        return "linear";
    }
}

const bad: IAxis = { type: getAxisType() };
//TS2322: Type '{ type: "linear" | "categorical"; }' is not assignable to type 'ILinearAxis | ICategoricalAxis'.
//    Type '{ type: "linear" | "categorical"; }' is not assignable to type 'ICategoricalAxis'.
//        Types of property 'type' are incompatible.
//            Type '"linear" | "categorical"' is not assignable to type '"categorical"'.
//                Type '"linear"' is not assignable to type '"categorical"'.

const good: IAxis = { type: undefined };
good.type = getAxisType();

Expected behavior: Both should work
Actual behavior: The "bad" axis declaration fails with the error described

Thanks!

@hellochar
Copy link
Author

Related weirdness:

const axis: IAxis = { type: "categorical"; };

axis.type = "linear";
// errors here saying axis.type === "categorical"

Apparently it sees axis as type ICategoricalAxis even though I explicitly typedef-ed it as IAxis?

@ahejlsberg
Copy link
Member

For your example to type check with no errors we would have to consider types of the form { x: "foo" | "bar" } to be equivalent to { x: "foo" } | { x: "bar" }. But this sort of equivalence only holds for types with a single property and isn't true in the general case. For example, it wouldn't be correct to consider { x: "foo" | "bar", y: string | number } to be equivalent to { x: "foo", y: string } | { x: "bar", y: number } because the first form allows all four combinations whereas the second form only allows two specific ones.

In your example, if all that ever differs between ILinearAxis and ICategoricalAxis is the type property, then you can just use a single interface IAxis { type: "linear" | "categorical" } and your code would work. But, if you actually have additional properties in ILinearAxis and ICategoricalAxis then you can't really structure your code the way you are.

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label Nov 6, 2016
@mhegazy mhegazy closed this as completed Dec 29, 2016
eps1lon added a commit to eps1lon/poe-react-item that referenced this issue Feb 27, 2018
Creation was not possible and we can achieve the same thing with
"crit" in props. See also microsoft/TypeScript#12052
@RyanCavanaugh
Copy link
Member

Ref #8289

@microsoft microsoft locked and limited conversation to collaborators Jul 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants