Created
March 28, 2018 13:57
-
-
Save andyedinborough/cf1dca5844e86620d183e09dea47d125 to your computer and use it in GitHub Desktop.
Revisions
-
andyedinborough created this gist
Mar 28, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,72 @@ 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()} /> */} </> );