Skip to content

Instantly share code, notes, and snippets.

@pzi
Last active July 23, 2019 03:30
Show Gist options
  • Save pzi/9d848f9442a08940dab2a0f1af52d94a to your computer and use it in GitHub Desktop.
Save pzi/9d848f9442a08940dab2a0f1af52d94a to your computer and use it in GitHub Desktop.
TypeScript: Conditional types and discriminated unions & narrowing
type Block = Important | Emphasis | Regular
type BK = Block['kind']
type Important = { kind: 'important'; important: string }
type Emphasis = { kind: 'emphasis'; emphasis: string }
type Regular = { kind: 'text'; text: string }
type SmartOpts<T extends Block['kind']> = Extract<Block, { kind: T }>
type RegularOptions = SmartOpts<'text'>
declare function doBlock<T extends BK>(kind: T, opts: SmartOpts<T>): void
const importantOpts: Important = { kind: 'important', important: 'asdsda' }
const regularOpts: Regular = { kind: 'text', text: 'text' }
doBlock('important', importantOpts)
interface CommonProps {
className?: string
}
interface KindOne extends CommonProps {
kind: 'button'
something: string
}
interface KindTwo extends CommonProps {
kind: 'bigger-button'
label: string
}
type Props = KindOne | KindTwo
export const Button: React.FC<Props> = (props) => {
if (props.kind=== 'button') {
// now you know
// props.label doesn't exist
}
if (props.kind === 'bigger-button') {
// and again
// props.label exists
}
}
function Test() {
const t1 = <Button kind='button' something='foobar' /> // OK
const t2 = <Button kind='bigger-button' something='foobar' /> // Not OK
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment