Typescript
Posted on October 2, 2021
Tags: javascript
- Any project using node_modules requires webpack !
1 Example
- installing node_modules in a normal file directory and running a live-server will not work.
- You need webpack to build and link the node_modules.
- you will notice something like
import Graph from 'graphology'
and IDE will say it cant find graphology.
Webpack will build the /myproject/src
folder into static files in the /myproject/out
folder. BUT we must first make the index.html
manually first.
- myproject/
- package.json
- node_modules/
- dist/
- index.html
- src/
- index.js
mkdir myproject
mkdir src
mkdir dist
touch /myproject/dist/index.html
cd myproject
npm init
npm install --save-dev typescript
npm install --save-dev webpack webpack-cli
npm install sigma graphology
<!DOCTYPE html>
<html>
<head>
<title>hi</title>
</head>
<body>
<script type="module" defer src="main.js"></script>
<div id="sigma-container" style="height: 50vh;width: 70vw;"></div>
<h1>hi</h1>
</body>
</html>
{.json filename = tsconfig.json} { "compilerOptions": { "target": "ES2015", "module": "es2022", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "moduleResolution": "node", "forceConsistentCasingInFileNames": true, "strictPropertyInitialization": false }, "$schema": "https://json.schemastore.org/tsconfig", "display": "Recommended" }
...
"tsc": "tsc",
"build": "webpack --mode production",
npm run tsc
npm run build
2 Node modules
mkdir someproj
#all npm init is create a single package.json file
npm init
#install node modules
npm install typescript --save-dev
modify package.json “scripts” to include
"tsc" : "tsc"
create tsconfig.json
{
"compilerOptions": {
"target": "ES2015",
"module": "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true
},
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Recommended"
}
To build index.js from index.tsx, use npx tsc
or npm run tsc
npm install http-server
add to package.json “scripts” "dev": "http-server ."
- module
- es2022 - `import { something } as “somepath”
- commonjs -
require('something')
- target - affects output of js code
- es2022 - newest features but less compatible
- moduleResolution - how your project searches for module files in folder
- node - use this
- classic
- lib -
- “es2022”,“dom”
- “dom” gives us access to browser-based globals like
window
ordocument
- “dom” gives us access to browser-based globals like
- “es2022”,“dom”
3 Koans
3.1 Define Interfaces
export type User = {
: string;
name: number;
age: string;
occupation;
}
: User[] = [
export const users
{: 'Max Mustermann',
name: 25,
age: 'Chimney sweep'
occupation,
}
{: 'Kate Müller',
name: 23,
age: 'Astronaut'
occupation
};
]
function logPerson(user: User) {
export console.log(` - ${user.name}, ${user.age}`);
}
3.2 Type narrowing
interface User {: string;
name: number;
age: string;
occupation
}
interface Admin {: string;
name: number;
age: string;
role
}
export type Person = User | Admin;
: Person[] = [
export const persons
{: 'Max Mustermann',
name: 25,
age: 'Chimney sweep'
occupation,
}
{: 'Jane Doe',
name: 32,
age: 'Administrator'
role,
}
{: 'Kate Müller',
name: 23,
age: 'Astronaut'
occupation,
}
{: 'Bruce Willis',
name: 64,
age: 'World saver'
role
};
]
function logPerson(person: Person) {
export : string;
let additionalInformationif ("role" in person) { //THIS IS OUR EDIT
= person.role;
additionalInformation
} else {= person.occupation;
additionalInformation
}console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}
interface User {: 'user';
type: string;
name: number;
age: string;
occupation
}
interface Admin {: 'admin';
type: string;
name: number;
age: string;
role
}
export type Person = User | Admin;
: Person[] = [
export const persons: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
{ type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
{ type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
{ type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' }
{ type;
]
function isAdmin(person: Person) {
export .type === 'admin';
return person
}
function isUser(person: Person) {
export .type === 'user';
return person
}
function logPerson(person: Person) {
export : string = '';
let additionalInformationif (isAdmin(person)) {
= (person as Admin).role;
additionalInformation
}if (isUser(person)) {
= (person as User).occupation;
additionalInformation
}console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
/*
Intro:
Time to filter the data! In order to be flexible
we filter users using a number of criteria and
return only those matching all of the criteria.
We don't need Admins yet, we only filter Users.
Exercise:
Without duplicating type structures, modify
filterUsers function definition so that we can
pass only those criteria which are needed,
and not the whole User information as it is
required now according to typing.
Higher difficulty bonus exercise:
Exclude "type" from filter criterias.
*/
interface User {: 'user';
type: string;
name: number;
age: string;
occupation
}
interface Admin {: 'admin';
type: string;
name: number;
age: string;
role
}
export type Person = User | Admin;
: Person[] = [
export const persons: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
{ type
{: 'admin',
type: 'Jane Doe',
name: 32,
age: 'Administrator'
role,
}
{: 'user',
type: 'Kate Müller',
name: 23,
age: 'Astronaut'
occupation,
}
{: 'admin',
type: 'Bruce Willis',
name: 64,
age: 'World saver'
role,
}
{: 'user',
type: 'Wilson',
name: 23,
age: 'Ball'
occupation,
}
{: 'admin',
type: 'Agent Smith',
name: 23,
age: 'Administrator'
role
};
]
= (person: Person): person is Admin => person.type === 'admin';
export const isAdmin = (person: Person): person is User => person.type === 'user';
export const isUser
function logPerson(person: Person) {
export = '';
let additionalInformation if (isAdmin(person)) {
= person.role;
additionalInformation
}if (isUser(person)) {
= person.occupation;
additionalInformation
}console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}
function filterUsers(persons: Person[], criteria: Partial<User>): User[] {
export .filter(isUser).filter((user) => {
return persons= Object.keys(criteria) as (keyof User)[];
const criteriaKeys .every((fieldName) => {
return criteriaKeys=== criteria[fieldName];
return user[fieldName] ;
});
})
}
console.log('Users of age 23:');
filterUsers(
,
persons
{: 23
age
}.forEach(logPerson);
)
// In case if you are stuck:
// https://www.typescriptlang.org/docs/handbook/utility-types.html
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#predefined-conditional-types
4 refactor type-casting to generic
= Object.keys(criteria) as (keyof Person)[];
let criteriaKeys
= <T>(obj: T) => Object.keys(obj) as (keyof T)[]
let getObjectKeys = getObjectKeys(criteria) let criteriaKeys