Jean-David Daviet

Ajouter TypeScript à un project ReactJS existant

import React from 'react'; import './Controls.css'; const Controls = ({ children }) => ( <div className={"controls"}> {children} </div> ) export default Controls;
import { ReactNode } from 'react'; import './Controls.css'; const Controls = ({children} : { children: ReactNode} ) => ( <div className={"controls"}> {children} </div> ) export default Controls;
const Line = ( {x, y, width} : { x: number, y: number, width: number } ) => (
import React from 'react'; import NativeSelect from '@material-ui/core/NativeSelect'; import Input from '@material-ui/core/Input'; import InputLabel from '@material-ui/core/InputLabel'; const ControlsClef = ( { clef, onChange } ) => { clef = clef ? 1 : 0; return ( <div className="control"> <InputLabel shrink htmlFor="control-clef">Clef</InputLabel><br /> <NativeSelect value={clef} onChange={onChange} input={<Input name="clef" id="control-clef" />}> <option value={0}>Bass</option> <option value={1}>Treble</option> </NativeSelect> </div> ) } export default ControlsClef;
import React, { ChangeEvent } from 'react'; import NativeSelect from '@material-ui/core/NativeSelect'; import Input from '@material-ui/core/Input'; import InputLabel from '@material-ui/core/InputLabel'; const ControlsClef = ({ clef, onChange }: {clef: boolean, onChange: (event: React.ChangeEvent<HTMLSelectElement>, child: React.ReactNode) => void } ) => { return ( <div className="control"> <InputLabel shrink htmlFor="control-clef">Clef</InputLabel><br /> <NativeSelect value={clef} onChange={onChange} input={<Input name="clef" id="control-clef" />}> <option value={0}>Bass</option> <option value={1}>Treble</option> </NativeSelect> </div> ) } export default ControlsClef;

ControlsKeyboard

import { Component } from 'react'; class ControlsKeyboard extends Component { componentDidMount(){ document.addEventListener("keydown", this.props.stopRunning, false); } componentWillUnmount(){ document.removeEventListener("keydown", this.props.stopRunning, false); } render(){return null} } export default ControlsKeyboard;
import { Component } from 'react'; class ControlsKeyboard extends Component<{ stopRunning: EventListener; }> { componentDidMount(){ document.addEventListener("keydown", this.props.stopRunning, false); } componentWillUnmount(){ document.removeEventListener("keydown", this.props.stopRunning, false); } render(){return null} } export default ControlsKeyboard;

Component avec state

export class Home extends Component {
export interface IGlobalState { chosenScale: string, clef: boolean, time: string, running: boolean, tempo: number } export class Home extends Component<{}, IGlobalState> {

Import de fichiers locaux

import C2_note from './octave-2/C2.mp3';
const C2_note = require('./octave-2/C2.mp3');
export class Home extends Component { constructor(){ super(); } }
export class Home extends Component { constructor(){ super({}); } }
event: KeyboardEvent

Mutliple React Children

import React, { ReactChild } from 'react'; const Mesure = ({ children }: { children: ReactChild }) => ( <svg> {children} </svg> ) export default Mesure;
// // React Nodes // http://facebook.github.io/react/docs/glossary.html // ---------------------------------------------------------------------- type ReactText = string | number; type ReactChild = ReactElement | ReactText; interface ReactNodeArray extends Array<ReactNode> {} type ReactFragment = {} | ReactNodeArray; type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

On voit que ReactNode peut contenir un ReactFragment qui peut lui aussi contenir un un ReactNodeArray

import React, { ReactNode } from 'react'; const Mesure = ({ children }: { children: ReactNode }) => ( <svg> {children} </svg> ) export default Mesure;

Pour accéder à un index d’object, il faut que sa signature soit définie. Si on veut accéder à signatures[this.state.chosenScale]
Il faut rajouter:

[key: string]: { [key: string]: number }
export interface ISignature { sharps: { C: number, G: number, D: number, A: number, E: number, B: number, Fs: number, Cs: number }, flats: { C: number, F: number ,Bb: number ,Eb: number ,Ab: number ,Db: number ,Gb: number ,Cb: number } [key: string]: { [key: string]: number } } const signatures: ISignature = { sharps: { C: 0, G: 1, D: 2, A: 3, E: 4, B: 5, Fs: 6, Cs: 7 }, flats: { C: 0, F: 1, Bb: 2, Eb: 3, Ab: 4, Db: 5, Gb: 6, Cb: 7 } }

Je me suis rendu compte après qu’il est en fait possible de déclarer la signature en utilisant as comme on a l’habitude de le faire à d’autres endroit du code : as { [key: number]: ReactNode }

TypeScript n’aime que l’on retourne un tableau d’élements s’il n’est pas inséré dans un React.Fragment :

return lines.map(lineProps => <Line {...lineProps} />);
return ( <React.Fragment> { lines.map(lineProps => <Line {...lineProps} />) } </React.Fragment> );
let notes = []; for(let i = 0; i < 4; i++){ notes.push({ x : (i * staveWidth / 4) + (staveWidth / 8) - MN_centerNote, marginTop: marginTop, staveHeight: staveHeight, key: i, index: i, sounds: sounds }); }
let notes: INoteProps[] = []; for(let i = 0; i < 4; i++){ notes.push({ x : (i * staveWidth / 4) + (staveWidth / 8) - MN_centerNote, marginTop: marginTop, staveHeight: staveHeight, key: i, index: i, sounds: sounds }); }