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

t.taggedUnion doesn't accept array from 1.5.3 (tuple only) #261

Closed
benoitv-code opened this issue Jan 16, 2019 · 5 comments
Closed

t.taggedUnion doesn't accept array from 1.5.3 (tuple only) #261

benoitv-code opened this issue Jan 16, 2019 · 5 comments

Comments

@benoitv-code
Copy link

benoitv-code commented Jan 16, 2019

Since the 1.5.3 update, t.taggedUnion() doesn't accept arrays anymore, only tuples.

Example:

const test1 = t.type({
    version: t.literal('1')
});

const test2 = t.type({
    version: t.literal('2')
});

const allTests = [ test1, test2 ];

// Works
const taggedOK = t.taggedUnion(
    'version',
    [
        test1,
        test2
    ]
);

// Doesn't work
const taggedNotOK = t.taggedUnion(
    'version',
    allTests
);

// Doesn't work either
const taggedNotOKEither = t.taggedUnion(
    'version',
    [
        test1,
        test2
    ].map((v) => t.exact(v))
);

Error:

[ts]
Argument of type '(TypeC<{ version: LiteralC<"1">; }> | TypeC<{ version: LiteralC<"2">; }>)[]' is not assignable to parameter of type '[Tagged<"version", any, any>, Tagged<"version", any, any>, ...Tagged<"version", any, any>[]]'.
  Type '(TypeC<{ version: LiteralC<"1">; }> | TypeC<{ version: LiteralC<"2">; }>)[]' is missing the following properties from type '[Tagged<"version", any, any>, Tagged<"version", any, any>, ...Tagged<"version", any, any>[]]': 0, 1 [2345]
@benoitv-code benoitv-code changed the title t.taggedUnion doesn't accept array from 1.6.x (tuple only) t.taggedUnion doesn't accept array from 1.5.3 (tuple only) Jan 16, 2019
@gcanti
Copy link
Owner

gcanti commented Jan 16, 2019

@kunnix taggedUnion and union are now aligned with tuple and intersection, i.e. you have to prove to the type checker that you are passing a correct number of elements

@benoitv-code
Copy link
Author

@gcanti Which would be great if TypeScript had a nice way to hint for tuple types, but it's not the case yet and for now they're typed as variable-lengths arrays when stored in a variable or passed to .map() (see microsoft/TypeScript#10195 and microsoft/TypeScript#16656)

I understand this is an elegant way to deal with typing, but it currently prevents storing a list of types in a variable, or to automatically enclose a list of types inside a t.exact() (so, forces to copy-and-paste code when these patterns were used).

@gcanti
Copy link
Owner

gcanti commented Jan 16, 2019

Maybe a couple of helpers can help

const tuple = <T extends Array<unknown>>(...t: T): T => {
  return t
}

type MakeExact<T extends Array<t.HasProps>> = { [K in keyof T]: T[K] extends t.HasProps ? t.ExactC<T[K]> : never }

const makeExact = <T extends Array<t.HasProps>>(...elements: T): MakeExact<T> => {
  return elements.map(e => t.exact(e)) as any
}

// ok
const TU1 = t.taggedUnion('version', [test1, test2])

const allTests = tuple(test1, test2)

// ok
const TU2 = t.taggedUnion('version', allTests)

// ok
const TU3 = t.taggedUnion('version', makeExact(...allTests))

// ok
const TU4 = t.taggedUnion('version', makeExact(test1, test2))

@benoitv-code
Copy link
Author

Looks like a great workaround!

@benoitv-code
Copy link
Author

@gcanti You probably saw that already, but it might help: microsoft/TypeScript#29510

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants