0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptのアサーション

0
Posted at

はじめに

JavaScriptを業務で使うようになってから、理解が曖昧だったところを学び直しています。

今回はアサーションについてです。

まず、アサーションの説明の前に、型キャストとの違いを載せておきます。

### 実行タイミング 内容
型アサーション コンパイル時 コンパイラに型を伝えるだけ、実行できるがどうなるかはわからん
型キャスト 実行時 ある値の型を別の型に変換する、

つまりアサーションとはコンパイラにプログラマーが情報を付加している操作で実体としては変化してません。

なのでアサーションはTypeScriptの型推論の限界をプログラマーで補っているようなものです。型ガードによる絞り込み(narrowing)で解決できるなら型ガードの方が安全です。

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html?utm_source=chatgpt.com#type-assertions
公式ドキュメントでは、DOM要素の型を指定したい時に使っています。

TypeScriptでのアサーションは大きく分けて型アサーションとconst アサーションの2つあります。まずは型アサーションから

型アサーション

  • 「number を string」に型アサーションするなどの無茶な変換はできない
  • が、unknownを経由すると回避することは可能。ただし型安全が保証されないので非推奨です。
const num = 123;
// const a = num as string エラー
const b = num as never // コンパイラから見るとbはnever型となる
const str = num as unknown as string; // OKだが非推奨

型アサーションには2つの記法があります。以下の例は無理やりアサーションを使っているので、型ガードによる絞り込みをする方が安全だと思います。

as構文: (変数 as 型名)

function getValue(): string | number {
  return "Hello";
}

const value = getValue();

// console.log(value.length); エラー:numberの可能性があるため
const len = (value as string).length;
// 下の方が安全
if (typeof(value) ==='string'){
  const len = value.length;
  console.log(len);
}

アングルブラケット構文(angle-bracket syntax) : (<型名>変数)

書き方が違うだけでなく、アングルブラケット構文は.tsだと使えるが、JSXの構文と衝突するため.tsxでは使えないというデメリットがあります。これを見てアングルブラケット構文は読めるようにはしておいて、書くのはas構文だけにしようと思いました。
https://www.typescriptlang.org/docs/handbook/jsx.html?utm_source=chatgpt.com#the-as-operator

function getValue(): string | number {
  return "Hello";
}
const value = getValue();

// console.log(value.length); エラー:numberの可能性があるため
const len = (<string>value).length;

const アサーション

const は変数への再代入を禁止するだけで、オブジェクトのプロパティの変更は許可し、
as const は型推論に影響し、オブジェクトリテラルのプロパティを readonly として扱う
ものです。

const アサーションによる変更は以下のような感じ

  • プリミティブ値をリテラル型にする
  • オブジェクトリテラルのプロパティを readonly にする
    • リテラルの中で直接作ったオブジェクト は、ネスト先も readonly になる
    • 別オブジェクトを参照している場合、as const が固定しているのはそのプロパティなので、元のオブジェクトをreadonlyにしているわけではないので、書き換え可能
  • 配列リテラルを readonly tuple にする
let hello = "hello";
let bye = "bye" as const;
 // let bye: "bye" となり、リテラル型なので実質的に書き換えられないのでas const

let len = 10
const flag = 1
const user = {
  name: 'test',
  age: 20
}

const data = {
  status: "success",   // readonly status: "success";
  count: 1,            // readonly count: 1;
  position: [10, 20],  // readonly position: readonly [10, 20];
  address: {           // readonly address: {
    city: "Tokyo",     //   readonly city: "Tokyo";
    zip: 100,          //   readonly zip: 100;
  },                   // };
  len: len,            // readonly len: number;
  flag,                // readonly flag: 1;
  user                 // readonly user: { name: string; age: number; };
} as const; 

data.status = "fail"       //エラー
data.address.city = 'Osaka'//エラー
data.len = 1               //エラー
len = 1                    //元のオブジェクトまでreadonlyにはならない
user.name = 'fix'          //data.userにはオブジェクトの参照が入っているのでdata.user.nameも変わる
console.log(data)
data.user.name = 'fix'     //書き換え可能
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?