Skip to content

Instantly share code, notes, and snippets.

@andyedinborough
Created March 28, 2018 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyedinborough/cf1dca5844e86620d183e09dea47d125 to your computer and use it in GitHub Desktop.
Save andyedinborough/cf1dca5844e86620d183e09dea47d125 to your computer and use it in GitHub Desktop.
Demo of conditional types
import * as React from 'react';
type Parse<T> = { parse: (value: string) => T };
type MaybeParse<T> = T extends string ? {} : Parse<T>;
interface GenericTextboxBaseProps<TModel, TProperties extends keyof TModel> {
model: TModel;
name: TProperties;
display?: (prop: TModel[TProperties]) => string;
}
type GenericTextboxProps<TModel, TProperties extends keyof TModel, TProperty extends TModel[TProperties]> =
GenericTextboxBaseProps<TModel, TProperties> & MaybeParse<TProperty>;
interface GenericTextboxState {
}
export class GenericTextbox<
TModel,
TProperties extends keyof TModel,
TProperty extends TModel[TProperties]
> extends React.Component<GenericTextboxProps<TModel, TProperties, TProperty>, GenericTextboxState> {
render () {
const { model, name, display } = this.props;
return (
<input
name={name}
value={display ? display(model[name]) : String(model[name] || '')}
onChange={this.handleChange}
/>
);
}
private handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { value } = e.currentTarget;
const { model, name } = this.props;
const { parse } = this.props as GenericTextboxProps<TModel, TProperties, TProperty> as Parse<TProperty>;
if (parse) {
model[name] = parse(value);
} else {
model[name as string] = value;
}
};
}
interface Person {
name: string;
age: number;
}
const person: Person = { name: 'Steve', age: 34 };
export const test = () => (
<>
<GenericTextbox model={person} name="name" />
<GenericTextbox model={person} name="age" parse={(v: string) => parseInt(v, 10) || 0} />
{/*
error: dne doesn't exist in person
<GenericTextbox model={person} name="dne" />
error: parse prop missing
<GenericTextbox model={person} name="age" />
error: parse return type doesn't match person.age
<GenericTextbox model={person} name="age" parse={v => new Date()} />
*/}
</>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment