TypeScriptの基礎的な知識(メソッドデコレータ、プロパティデコレータ)について学ぶ
学んだこと
複数のデコレータを同時に使う方法
- デコレータ
- 下から上に実行される
- デコレータファクトリー
- 上から下に実行される
// この関数がデコレータファクトリ
function Logging(message: string){
return function (constructor: Function){
console.log(message)
}
}
// ここでフレームワークを作成
function Component(template: string, selector: string){
// 新しくインスタンスを生成
// templeteにはHTMLが格納されているため、innerHTMLにいれる
// textContentにはインスタンスで生成したnameをそのまま渡す
return function(constructor: { new(...args: any): {name: string} }){
const mountedElement = document.querySelector(selector);
const instance = new constructor();
if(mountedElement){
mountedElemet.innerHTML = templete;
mountedElement.querySelector("h1")!.textContent = instance.name;
}
}
}
// 複数定義しているため、デコレータを複数用意することは可能
@Component("<h1></h1>", "#app")
@Logging("LoggingUser")
Class User{
name = "Quill";
constructor(){
console.log("User was created!")
}
}
- html 側
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="dist/decorator.js" defer></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
戻り値にクラスを指定して、新しいクラスを作り出す方法
function Logging(message: string){
return function (constructor: Function){
console.log(message)
}
}
function Component(template: string, selector: string){
// 戻り値にクラスを返す
// コンストラクタで設定した内容をそのままコピペしてextendsにつける
return function<T extends { new(...args: any): {name: string} } >(constructor: { new(...args: any): {name: string} }){
// ここでクラスを返すようにする
return class extends constructor {
constructor(...args: any) {
super(...args);
const mountedElement = document.querySelector(selector);
const instance = new constructor();
if(mountedElement){
mountedElemet.innerHTML = templete;
mountedElement.querySelector("h1")!.textContent = instance.name;
}
}
}
}
}
@Component("<h1></h1>", "#app")
@Logging("LoggingUser")
Class User{
name = "Quill";
constructor(){
console.log("User was created!")
}
}
プロパティデコレータ
- デコレータの前にプロパティデコレータが最初に実行される ``` // プロパティは2つ引数を設定する // 1つ目: プロトタイプ(インスタンスが共有する関数やプロパティの土台、設計図のようなもの) // 2つ目: キー情報 function PropertyLogging(target: any, propertyKey: string){ console.log() }
@Component(“<h1></h1>”, “#app”) @Logging(“LoggingUser”) Class User{ @PropertyLogging name = “Quill”; constructor(){ console.log(“User was created!”) } }
### メソッドデコレータ
function PropertyLogging(target: any, propertyKey: string){ console.log() }
// 基本的にプロパティデコレータと引数は一緒だが、1つ追加になる // PropertyDescriptor: メソッドの中身(実行内容や設定)が入っているオブジェクト // メソッドを書き換えたりすることができる function MethodLogging(target: any, propertyKey: string, descriptor: PropertyDescriptor){ console.log(descriptor) }
@Component(“<h1></h1>”, “#app”) @Logging(“LoggingUser”) Class User{ @PropertyLogging name = “Quill”; constructor(){ console.log(“User was created!”) }
@MethodLogging greeting(){ console.log(“Hello”) } } ```