Skip to content

Instantly share code, notes, and snippets.

@dcecile
Last active September 2, 2018 00:32
Show Gist options
  • Select an option

  • Save dcecile/3e089b5cd534cdd4f6690f4bb87280de to your computer and use it in GitHub Desktop.

Select an option

Save dcecile/3e089b5cd534cdd4f6690f4bb87280de to your computer and use it in GitHub Desktop.
TypeScript discriminated unions
enum EventType {
connectTwitter,
addSource,
}
type EventPayload = {
[EventType.connectTwitter]: { id: number }
[EventType.addSource]: { x: string; y: string }
}
function buildEvent<TV extends EventType>(
type: TV,
payload: EventPayload[TV]
) {
return { type, payload }
}
export const x = buildEvent(EventType.connectTwitter, {
id: 4,
})
export const y = buildEvent(EventType.connectTwitter, {
x: 'a',
y: 'b',
})
function literal<T extends number>(value: T): T
function literal<T extends string>(value: T): T
function literal<T>(value: T): T {
return value
}
const EventType = {
connectTwitter: literal(0),
addSource: literal(1),
}
type EventType = typeof EventType
type EventPayload = {
connectTwitter: { id: number }
addSource: { x: string; y: string }
}
export const c: EventType['connectTwitter'] = 0
function buildEvent<
TN extends keyof EventType & keyof EventPayload
>(type: EventType[TN], payload: EventPayload[TN]) {
return { type, payload }
}
export const x = buildEvent<'connectTwitter'>(
EventType.connectTwitter,
{
id: 4,
}
)
export const y = buildEvent<'connectTwitter'>(
EventType.connectTwitter,
{
x: 'a',
y: 'b',
}
)
function literal<T extends number>(value: T): T
function literal<T extends string>(value: T): T
function literal<T>(value: T): T {
return value
}
const EventType = {
connectTwitter: literal(0),
addSource: literal(1),
}
type EventType = typeof EventType
const EventTypeName = {
[0]: literal('connectTwitter'),
[1]: literal('addSource')
}
type EventTypeName = typeof EventTypeName
type EventPayload = {
connectTwitter: { id: number }
addSource: { x: string; y: string }
}
export const c: EventType['connectTwitter'] = 0
function buildEvent<TV extends keyof EventTypeName>(
type: TV,
payload: EventPayload[EventTypeName[TV]]
) {
return { type, payload }
}
export const x = buildEvent(EventType.connectTwitter, {
id: 4,
})
export const y = buildEvent(EventType.connectTwitter, {
x: 'a',
y: 'b',
})
function iso<T>(obj: { [K in keyof T]: K }) {
return obj
}
const EventType = iso({
connectTwitter: "connectTwitter",
addSource: "addSource",
})
type EventType = typeof EventType
type EventPayload = {
connectTwitter: { id: number }
addSource: { x: string; y: string }
}
function buildEvent<
TV extends keyof EventType & keyof EventPayload
>(type: TV, payload: EventPayload[TV]) {
return { type, payload }
}
export const x = buildEvent(
EventType.connectTwitter,
{
id: 4,
}
)
export const y = buildEvent(
EventType.connectTwitter,
{
x: 'a',
y: 'b',
}
)
const EventType = {
connectTwitter: 0 as 0,
addSource: 1 as 1,
}
type EventType = typeof EventType
type EventPayload = Pick<
{
connectTwitter: { id: number }
addSource: { x: string; y: string }
},
keyof EventType
>
type Pairs = {
[K in keyof EventType]: [EventType[K], EventPayload[K]]
}[keyof EventType]
function buildEvent<T extends Pairs>(pair: T) {
const [type, payload] = pair
return { type, payload }
}
export const x = buildEvent([
EventType.connectTwitter,
{
id: 4,
},
])
export const y = buildEvent([
EventType.connectTwitter,
{
x: 'a',
y: 'b',
},
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment