Open31

JavaScript/TypeScript

tatatsurutatatsuru

tab移動をした際に起こる現象

tabキーで移動してから処理を行いたい!
そんな時に

this.focusElement = document.activeElement;

現在フォーカスが当たっている部分を取得するとbodyが取得されてしまう。(思ったところを取得できていない。)
これはtabで移動している間に

this.focusElement = document.activeElement;

が走ってしまっているから。
setTimeoutで待つのがいいのか?

tatatsurutatatsuru

APIクライアント

Chat GPT

APIクライアントは、アプリケーションやサービスが外部のAPI(Application Programming Interface、アプリケーションプログラミングインターフェース)を使用して通信するためのコンポーネントです。APIクライアントは、外部のサーバーやサービスとデータを送受信するためにAPIを利用し、必要な情報を取得したり、リクエストを送信したりする役割を担います。

// GitHubのAPIを使用してリポジトリ情報を取得するAPIクライアントの例
function getGitHubRepositoryInfo(username, repositoryName) {
    const url = `https://api.github.com/repos/${username}/${repositoryName}`;

    // GitHub APIにGETリクエストを送信し、レスポンスを取得
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok.');
            }
            return response.json();
        })
        .then(repositoryInfo => {
            // レスポンスが成功した場合、リポジトリ情報を返す
            return repositoryInfo;
        })
        .catch(error => {
            console.error('There has been a problem with your fetch operation:', error);
        });
}

// 例としてOpenAIのGPT-3リポジトリ情報を取得する
const username = "openai";
const repositoryName = "gpt-3";

getGitHubRepositoryInfo(username, repositoryName)
    .then(repoInfo => {
        if (repoInfo) {
            console.log("リポジトリ情報:");
            console.log(`名前: ${repoInfo.name}`);
            console.log(`説明: ${repoInfo.description}`);
            console.log(`スター数: ${repoInfo.stargazers_count}`);
            console.log(`フォーク数: ${repoInfo.forks_count}`);
        } else {
            console.log("リポジトリ情報を取得できませんでした");
        }
    });

tatatsurutatatsuru

OpenAPI Generator

yamlで書いた設計図からclientを作成してくれる。

# OpenAPI Generatorをインストール
npm install @openapitools/openapi-generator-cli -g

# JavaScriptのクライアントコードを生成
openapi-generator-cli generate -i openapi.yaml -g javascript -o ./generated-client

これにより、openapi.yamlからJavaScriptのクライアントコードが生成され、./generated-clientディレクトリに保存されます。

// 生成されたクライアントコードを利用してAPIを呼び出す例
const MyApiClient = require('./generated-client'); // 生成されたクライアントコードのパスを指定

const client = new MyApiClient.DefaultApi();

// 生成されたクライアントコードの関数を使ってAPIを呼び出す
client.getSomeData()
    .then(response => {
        console.log('APIからのレスポンス:', response);
    })
    .catch(error => {
        console.error('API呼び出しでエラーが発生しました:', error);
    });

このようにして、OpenAPI Generatorを使用すると、APIの仕様書から自動的にJavaScriptのクライアントコードを生成し、それを使ってAPIを利用することができます。

tatatsurutatatsuru

d.ts

自身のプロジェクトでTypeScriptでコーディングする場合は型を宣言することにより、IDEやエディターの補完機能やコードチェックを行えます。しかし外部のパッケージ(npm)を利用する場合は型定義ファイルが含まれているとは限りません。

https://typescriptbook.jp/reference/declaration-file

tatatsurutatatsuru

ジェネリクスとマップ型

https://typescriptbook.jp/reference/generics
https://typescriptbook.jp/reference/builtin-api/map

型を変数のように扱うことができる。

// ジェネリクス例
type MyPick<TodoArg, KeyArg extends keyof TodoArg> = {
  [key in KeyArg]: TodoArg[key]
}

// これを第一引数に入れてる
interface Todo {
  title: string
  description: string
  completed: boolean
}

// 実際に使用するとこんな感じ
MyPick<Todo, "title">

KeyArg extends keyof TodoArgは、KeyArgが型TodoArgのkeyということを示している。
⇨keyArgはtitle,description,completedが入ってくるということになる。(それ以外は×)

例えば

MyPick<Todo, "title" | "description">

という使い方をしたときに[key in KeyArg]: TodoArg[key]はjsのmapのような挙動をとる。

  • [key in KeyArg] = titleだったら、TodoArg[title]となり、stringが返ってくる
  • [key in KeyArg] = descriptionだったら、TodoArg[description]となり、stringが返ってくる

上記のような挙動を取り

MyPick<Todo, "title" | "description">interface expectedType {
  title: string
  description: string
}

となる

tatatsurutatatsuru

Readonlyな型

https://typescriptbook.jp/reference/type-reuse/utility-types/readonly
https://typescriptbook.jp/reference/values-types-variables/object/readonly-property

// Readonly例
type MyReadonly<T> = {
  readonly [P in keyof T]: T[P]
}

// これを第一引数に入れてる
interface Todo {
  title: string
  description: string
  completed: boolean
  meta: {
    author: string
  }
}

// 実際に使用するとこんな感じ
MyReadonly<Todo1>

これもマップ型の一種とreadonlyプロパティを使用。

  • [P in keyof T]ではtitle,description,completed,metaなどが入ってくる
  • T[P]はTodoのtitle,description,completed,metaに一致する型が入ってくる
tatatsurutatatsuru

extends

色々な使われ方をするらしい

型引数に制約をつける

https://typescriptbook.jp/reference/generics/type-parameter-constraint#型引数に制約をつける

インターフェースの拡張(継承)

interface Person {
    name: string,
    age: number
}

interface PersonDetail extends Person {
    birthplace: string,
    adress: string,
    .......
}


// PersonDetailは以下と同じになる
interface PersonDetail {
    name: string,
    age: number,
    birthplace: string,
    adress: string,
    .......
}

条件式みたいに使える

type First<T extends any[]> = T extends [] ? never : T[0]

三項演算子みたい!

tatatsurutatatsuru

PropertyKey

https://www.totaltypescript.com/concepts/propertykey-type

In TypeScript, PropertyKey is a global type in TypeScript that represents the data type of a property key. It can be a string, a symbol, or a number.

TypeScriptでは、PropertyKeyはプロパティキーのデータ型を表すグローバル型である。文字列、シンボル、数値のいずれかである。

tatatsurutatatsuru

配列を引数でもらった時のマップ型

// 例
type TupleToObject<T extends readonly PropertyKey[]> = {
  [P in T[number]]: P
}

// それぞれの型
const sym1 = Symbol(1)
const sym2 = Symbol(2)
const tupleSymbol = [sym1, sym2] as const

// 実際に使用するとこんな感じ
TupleToObject<typeof tupleSymbol>

Symbol

https://typescriptbook.jp/reference/values-types-variables/symbol

T[number] となる理由

Tが配列またはタプル型だから。

tatatsurutatatsuru

Non-null assertion operator

https://qiita.com/zigenin/items/364264a6cf635b962542

プログラマがコンパイラに対して、この変数はundefinedやnullになることはありません、と教える記述。
不正確だが、型<T>があるとして、型<T | undefined | null>を型<T>に静的にcastしていると考えると分かりやすい。
変換前の型は、型<T | undefined>でも型<T | null>でもOK。