sam-goodwin / punchcard

Type-safe AWS infrastructure.
Apache License 2.0
506 stars 20 forks source link

Support a union Shape or polymorphic types #105

Open sam-goodwin opened 4 years ago

sam-goodwin commented 4 years ago

It should be possible to define union types for things such as polymorphic DynamoDB Tables.

See: https://github.com/punchcard/punchcard/issues/103 for customer request.

Ex. usage:

union([string, integer, A, array(string)])
sam-goodwin commented 4 years ago

Should also support tagged unions. I wonder if we could introduce literal types for this use case:

class A extends Record({
  tag: 'A'
}) {}

class B extends Record({
  tag: 'B'
}) {}

const taggedUnion = union([A, B], 'tag');
sam-goodwin commented 4 years ago

Useful mechanic for extracting a type from a tagged-union by its tag.

https://gcanti.github.io/typelevel-ts/modules/index.ts.html#taggedunionmember-type-alias

(Copied from above link)

Signature

export type TaggedUnionMember<A extends object, Tag extends keyof A, Value extends A[Tag]> = Extract<
  A,
  Record<Tag, Value>
>

Example

import { TaggedUnionMember } from 'typelevel-ts'

type A = { tag: 'A'; a: string }
type B = { tag: 'B'; b: number }
type C = A | B
export type Result = TaggedUnionMember<C, 'tag', 'A'> // A
sam-goodwin commented 4 years ago

As per https://github.com/punchcard/punchcard/pull/108:

I just realized that the pattern: class X extends <function call> is the "Shape equivalent" of TS's type X = <type computation>. This will come in handy for expressing all sorts of type computations, like unions:

// in the TypeScript type-system
type A = string | number;
// in the Shape type-system
class A extends Union([string, number]) {}
sam-goodwin commented 4 years ago

Pretty meta to now also have a mapped type equivalent in the data-based Shape type-system .. woah. "Shape" is turning out to be an incredibly expressive and powerful DDL.