TypeScript
, meet React
Thinking about our application's input and output is what allows us to understand our React code, and what (hopefully) makes it bug-free
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
const myName = "Kristian Freeman";
const nameLength = name => console.log(name.length);
nameLength(myName) // 16
first
and last
const name = {
first: "Kristian",
last: "Freeman"
}
nameLength(name) // undefined
const nameLength = (name: string) => console.log(name.length);
name.ts:6:12 - error TS2345: Argument of
type '{ first: string; last: string; }' is not
assignable to parameter of type 'string'.
6 nameLength(myName);
~~~~~~
// Numbers
let myAge: number = 24;
let gasPrice: number = 2.95;
// Booleans
let isPresenting: boolean = true;
let isEating: boolean = false;
// Strings
let firstName: string = "Kristian";
// Arrays
let languages: string[] = ["JavaScript", "Ruby", "Elixir"];
let languages: Array<string> = ["JavaScript", "Ruby", "Elixir"];
// Tuples
let information: [string, string, number] = ["Kristian", "Freeman", 24];
let information: [string, string, number];
// Error
information = ["Kristian", 24];
// Enum
enum State {WA, OR, CA}
let california: State = State.CA;
// Indexed enums
enum State {WA, OR, CA}
// Notice: `string`, not `State`
let california: string = State[2]
console.log(california) // "CA"
let myAge = 24; // type is `number`
let myName = "Kristian Freeman"; // type is `string`
let myAge = 24;
myAge.toUppercase();
// MyAge.ts(2,7): error TS2339: Property 'toUpperCase'
// does not exist on type 'number'.
interface Person {
firstName: string;
lastName: string;
age: number;
}
// OK
const me: Person = {
firstName: "Kristian",
lastName: "Freeman",
age: 25
}
// Error
const you: Person = {
firstName: "Other",
lastName: "Person"
}
interface Person {
firstName: string;
lastName: string;
age?: number;
}
// OK
const me: Person = {
firstName: "Kristian",
lastName: "Freeman",
age: 25
}
// OK
const you: Person = {
firstName: "Other",
lastName: "Person"
}
class Person {
firstName: string;
lastName: string;
age: number;
constructor(first: string, last: string, age: number) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
}
let me = new Person("Kristian", "Freeman", 24);
console.log(me.firstName);
console.log(me.lastName);
me.age + 10;
In React, we reason about how our components work by asking: what are the props? What is the state?
// JavaScript
class HelloComponent extends React.Component = {
render() {
return <p>{this.props.message}</p>;
}
}
// TypeScript
class HelloComponent: React.Component<Props, State> = {
render() {
return <p>{this.props.message}</p>;
}
}
interface IProps {
message: string;
}
class HelloComponent: React.Component<IProps, {}> = {
render() {
return <p>{this.props.message}</p>;
}
}
interface IProps {
message: string; // required
paragraphClass?: string; // optional
}
class HelloComponent: React.Component<IProps, {}> = {
render() {
const { message, paragraphClass } = this.props;
return <p className={paragraphClass}>
{message}
</p>;
}
}
<HelloComponent message={0} /> // Error
<HelloComponent message="Hello, world!" /> // OK
<HelloComponent
message="Hello, world!"
paragraphClass={0} /> // Error
<HelloComponent
message="Hello, world!"
paragraphClass="big" /> // OK
yarn add @types/react @types/react-dom
ts-loader
.js
files to .ts
(or .tsx
for .jsx
files)ts-lint
ts-lint
plugin installation