[A-00194] Typescript入門
typescript入門用の記事です。
主にdeno,bunを使って実行します。
brew install deno
brew install oven-sh/bun/bun
適当なプロジェクトを作成します。
mkdir ts-project
cd ts-project
deno init
mkdir ts-project
cd ts-project
bun init
・Helloworldしてみる
console.log("Hello,typescript!");
下記のコマンドで実行します。
deno run hello.ts
$ deno run hello.ts
Hello,typescript!
・クラスを作ってみる
次はクラスを作ってみます。ディレクトリ構成は下記の通りです。

personクラスを作成します。
export class Person {
name: string;
age: number;
address: string;
constructor(name: string, age: number, address: string) {
this.name = name;
this.age = age;
this.address = address;
}
private sayName(): void {
console.log("My name is " + this.name + "!");
}
public getName(): string {
this.sayName();
return this.name;
}
}
次に実行するプログラムを書きます。
import { Person } from './clsdir/person.ts'
const p1 = new Person('takeshi', 14, 'tokyo');
var name:string = p1.getName();
console.log("His name is " + name + ".");
実行すると下記にようになります。
$ deno run main.ts
My name is takeshi!
His name is takeshi.
・インターフェースを作ってみる
先ほど作成したPersonをインターフェースにしてBusinessPersonクラスを実装してみます。
export interface Person {
getName():string;
getAge():number;
getAddress():string;
getCountry():string;
}
import { Person } from './person.ts';
export class BusinessPerson implements Person {
private name: string;
private age: number;
protected address: string;
private country: string;
private job: string;
public constructor(name:string, age:number,
address:string, country:string, job:string) {
this.name = name;
this.age = age;
this.address = address;
this.country = country;
this.job = job;
}
public introduce(): void {
console.log("Nice to meet you.");
console.log("My name is " + this.name + ". I'm " + this.age + " years old.");
console.log("I'm now live in " + this.country + ", at " + this.address + ". ");
console.log("I'm work as " + this.job);
}
public getName(): string {
return this.name;
}
public getAge(): number {
return this.age;
}
public getAddress(): string {
return this.address;
}
public getCountry(): string {
return this.country;
}
}
下記が実行プログラムです。
import { BusinessPerson } from './clsdir/business_person.ts'
const bp1 = new BusinessPerson("takeshi", 14 , "tokyo", "Japan", "student");
bp1.introduce();
$ deno run main.ts
Nice to meet you.
My name is takeshi. I'm 14 years old.
I'm now live in Japan, at tokyo.
I'm work as student
・Promiseの試しに動かしてみる
promiseとは非同期処理などに使用する関数です。初心者なのでそれだけしか分かりませんが、こいつの中身がどうなっているかを調べるため、下記のコードを実行してみます。
// Promiseの中身
console.log(new Promise(() => {}));
// 成功の場合
console.log(new Promise((resolve, reject) => resolve("Success.")));
// 失敗の場合
console.log(new Promise((resolve, reject) => reject("Failed.")));
// 成功の場合
console.log(new Promise((resolve, reject) => resolve("Success.")).then((text) => console.log( text + "I'm happy.")));
// 失敗の場合
console.log(new Promise((resolve, reject) => reject("Failed.")).catch((text) => console.log( text + "I'm bored.")));
user@usernoMBP test-vite1 % bun run test_main.tsx
Promise { <pending> }
Promise { <resolved> }
Promise { <rejected> }
Promise { <pending> }
Promise { <pending> }
Success.I'm happy.
Failed.I'm bored.
error: Failed.
・BunでReactを動かす
bunを使ってReactを動かす方法をメモ
bun add react
bun create react-app react-test-app
cd react-test-app
bun start
・TypescriptのReatチュートリアルをやってみる。
TS公式サイトにてReactのチュートリアルがあったのでそれをやってみます。Bunを使用する都合でViteでやってみます。
https://typescriptbook.jp/tutorials/react-like-button-tutorial
bun create vite test-vite1
> React
> Typescript
cd test-vite1
bun install
viteプロジェクトが作成できたら下記のコマンドで動作検証します。
bun run dev
vite+Reactの画面が表示されたらOKです。
src配下のApp.tsxを変更します。
import React, { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function LikeButton() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<span className='likeButton' onClick={handleClick}>
❤️ {count}
</span>
);
}
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<div className='App'>
<header className='App-header'>Typescriptはいいぞ</header>
<br />
<LikeButton />
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App
実行すると下記のように表示されます。

・Design Patternを学ぶ
typescriptでデザインパターンを学習します。
・FactoryMethod
abstract class Creator {
public abstract factoryMethod(): Product;
public someOperation(): string {
const product = this.factoryMethod();
return `Creator: The same creator's code has just worked with ${product.operation()}`;
}
}
class ConcreteCreator1 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct1();
}
}
class ConcreteCreator2 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct2();
}
}
// Interface
interface Product {
operation(): string;
}
// ConcreteClass of Product
class ConcreteProduct1 implements Product {
public operation(): string {
return 'This is first your product.';
}
}
// ConcreteClass of Product
class ConcreteProduct2 implements Product {
public operation(): string {
return 'This is 2nd your product.'
}
}
function clientCodeFactoryMethod(creator: Creator) {
console.log('Client: I\'m not aware of the creator\'s class, but it still works.');
console.log(creator.someOperation());
}
console.log('App: Launched with the ConcreteCreator1.');
clientCodeFactoryMethod(new ConcreteCreator1());
console.log('');
console.log('App: Launched with the ConcreteCreator2.');
clientCodeFactoryMethod(new ConcreteCreator2());
user@usernoMBP ts-catalog % deno factory_method.ts
App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with This is first your product.
App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with This is 2nd your product.
・Prototype
class Prototype {
public primitive: any;
public component: object;
public circularReference: ComponentWithBackReference;
public clone(): this {
const clone = Object.create(this);
clone.component = Object.create(this.component);
clone.circularReference = {
...this.circularReference,
prototype: {...this},
};
return clone;
}
}
class ComponentWithBackReference {
public prototype;
constructor(prototype: Prototype) {
this.prototype = prototype;
}
}
function clientCodeProtoType() {
const p1 = new Prototype();
p1.primitive = 245;
p1.component = new Date();
p1.circularReference = new ComponentWithBackReference(p1);
const p2 = p1.clone();
if (p1.primitive === p2.primitive) {
console.log('Primitive field values have been carried over to a clone. Yay!');
} else {
console.log('Primitive field values have not been copied. Booo!');
}
if (p1.component === p2.component) {
console.log('Simple component has not been cloned. Booo!');
} else {
console.log('Simple component has been cloned. Yay!');
}
if (p1.circularReference === p2.circularReference) {
console.log('Component with back reference has not been cloned. Booo!');
} else {
console.log('Component with back reference has been cloned. Yay!');
}
if ( p1.circularReference.prototype === p2.circularReference.prototype) {
console.log('Component with back reference is linked to original object. Booo!');
} else {
console.log('Component with back reference is linked to the clone. Yay!');
}
}
clientCodeProtoType();
user@usernoMBP ts-catalog % deno prototype.ts
Primitive field values have been carried over to a clone. Yay!
Simple component has been cloned. Yay!
Component with back reference has been cloned. Yay!
Component with back reference is linked to the clone. Yay!
・Singleton
class Singleton {
static #instance: Singleton;
static #value: string;
private constructor() {}
public static get instance(): Singleton {
if (!Singleton.#instance) {
Singleton.#instance = new Singleton();
}
return Singleton.#instance;
}
public setHello(value: string) {
Singleton.#value = value;
}
public sayHello(): string {
return Singleton.#value;
}
}
function clientCodeSingleton() {
const s1 = Singleton.instance;
const s2 = Singleton.instance;
s1.setHello("Guten morgen");
if (s1 === s2) {
console.log(
'Singleton works, both variables contain the same instance.'
);
console.log('s1 is ' + s1.sayHello());
console.log('s2 is ' + s2.sayHello());
} else {
console.log('Singleton failed, variables contain different instances.');
}
}
clientCodeSingleton();
user@usernoMBP src % bun singleton.ts
Singleton works, both variables contain the same instance.
s1 is Guten morgen
s2 is Guten morgen
・Appendix
参考文献はこちら
https://qiita.com/nogson/items/86b47ee6947f505f6a7b
https://qiita.com/Tsuyoshi84/items/e74109e2ccc0f4e625aa
https://qiita.com/tatsumin0206/items/5835a64cb32ace41e0b1
https://qiita.com/kushidangoAnne/items/85c147aa694e4e6cc008
https://qiita.com/yukiji/items/3db06601ece7f080b0d0
https://zenn.dev/estra/books/ts-the-minimum/viewer/2-tsmini-start-deno-ts
https://hono.dev/getting-started/basic
https://www.freecodecamp.org/news/learn-typescript-beginners-guide
https://docs.deno.com/runtime/reference/cli/init
https://refactoring.guru/ja/design-patterns/factory-method/typescript/example
https://zenn.dev/kotopasi/articles/7a623823e325b8
https://typescriptbook.jp/tutorials/react-like-button-tutorial
https://zenn.dev/ak/articles/c21609fd3b0fdc
https://zenn.dev/ak/articles/00616eb99523c2
https://zenn.dev/ak/articles/dc23436b241a84
コメントを残す