TypeScript workshop for FIU students.
[MUST] Install Node.js with npm.
[MUST] Signup for Azure Cognitive Service free trial: Azure Cognitive Service
Once in the site click on `Language APIs`
On the blue `Guest` option click `Get Started`
Accept terms and conditions
Sign in with your preferred account
If do not have any MS, FB, linkedIn or Github account, come see us.
[Recommended] You may also want to get a sense of the basics with React.
We're going to use the create-react-app because it sets some useful tools and canonical defaults for React projects. This is just a command-line utility to scaffold out new React projects.
npm install -g create-react-appWe'll create a new project called my-app:
create-react-app my-app --scripts-version=react-scripts-tsreact-scripts-ts is a set of adjustments to take the standard create-react-app project pipeline and bring TypeScript into the mix.
At this point, your project layout should look like the following:
my-app/
├─ .gitignore
├─ images.d.ts
├─ node_modules/
├─ public/
├─ src/
│ └─ App.css
| └─ App.test.tsx
| └─ App.tsx
| └─ index.css
| └─ index.tsx
| └─ log.svg
| └─ registerServiceWorker.ts
| └─ utils/
└─ service.ts
├─ package.json
├─ tsconfig.json
├─ tsconfig.prod.json
├─ tsconfig.test.json
└─ tslint.json
Of note:
tsconfig.jsoncontains TypeScript-specific options for our project.- We also have a
tsconfig.prod.jsonand atsconfig.test.jsonin case we want to make any tweaks to our production builds, or our test builds.
- We also have a
tslint.jsonstores the settings that our linter, TSLint, will use.package.jsoncontains our dependencies, as well as some shortcuts for commands we'd like to run for testing, previewing, and deploying our app.publiccontains static assets like the HTML page we're planning to deploy to, or images. You can delete any file in this folder apart fromindex.html.srccontains our TypeScript and CSS code.index.tsxis the entry-point for our file, and is mandatory.images.d.tswill tell TypeScript that certain types of image files can beimport-ed, which create-react-app supports.
Our testing tool, Jest, expects some form of source control (such as Git or Mercurial) to be present. For it to run correctly, we'll need to initialize a git repository.
git init
git add .
git commit -m "Initial commit."Note: if you've cloned this repository, you won't have to run the above at all.
The TSLint configuration that react-scripts-ts sets us up with is a bit overzealous. Let's fix that up.
{
- "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
+ "extends": [],
+ "defaultSeverity": "warning",
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts"
]
}
}Configuring TSLint is out of the scope of this starter, but you should feel free to experiment with something that works for you.
Running the project is as simple as running
npm run startThis runs the start script specified in our package.json, and will spawn off a server which reloads the page as we save our files.
Typically the server runs at http://localhost:3000, but should be automatically opened for you.
This tightens the iteration loop by allowing us to quickly preview changes.
import React, { ComponentProps } from 'react';
const List = (props: ComponentProps<any>) => (
<ul>
{
props.items.map((item: string, index: number) => <li key={index}>{item}</li>)
}
</ul>
);
export default List;
Create config.ts
export class Config {
public static host: string = "https://api.cognitive.microsoft.com";
public static configs = "?mkt=en-US&mode=proof";
public static path = "bing/v7.0/spellcheck";
public static key = "";
}
Create service.ts
import request from 'request-promise'
import { Config } from './config';
export class Service {
private uri = Config.host + "/" + Config.path + "/" + Config.configs;
private azureKey:string;
constructor(key: string) {
this.azureKey = key;
}
public async checkSpelling(phrase: string): Promise<void> {
const options = {
method : 'POST',
uri : this.uri,
// tslint:disable-next-line:object-literal-sort-keys
headers : {
'Content-Length' : phrase.length + 5,
'Content-Type' : 'application/x-www-form-urlencoded',
'Ocp-Apim-Subscription-Key' : this.azureKey,
},
body: "text=" + phrase
};
try {
return await request(options);
} catch (error) {
// tslint:disable-next-line:no-console
console.log(error);
}
}
}
Make sure you have the following imports:
import * as React from 'react';
import './App.css';
import List from './List';
import logo from './logo.svg';
import { Config } from './utils/config';
import { Service } from './utils/service'
Declare interface:
export interface IMyCustomProps {
items: string[]
value: ''
};
const service = new Service(Config.key);
Use iterface:
class App extends React.Component<{}, IMyCustomProps>
Make constructor:
constructor(props: any) {
super(props);
this.state = {
items: [],
value: ''
}
}
Add onSubmit function:
public onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (await this.isCorrectSpelling()) {
this.setState({
items: [...this.state.items, this.state.value],
value: ''
});
}
}
Add onChange function:
public onChange = (event: any) => {
this.setState({value: event.target.value});
}
Add isCorrectSpelling:
public async isCorrectSpelling(): Promise<boolean> {
return await service.checkSpelling(this.state.value).then((response: any) => {
if (response && response.flaggedToken.length > 0) {
return false;
} else {
return true;
}
})
}
Change what we render:
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React Todo App</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
<List items={this.state.items}/>
<form className="App" onSubmit={this.onSubmit}>
<input value={this.state.value} onChange={this.onChange} />
<button>Submit</button>
</form>
</div>