Pythonでtypingを使って型を操ろう – Literal, TypeGuard, TypedDict, TypeAlias

今回は型で値を縛る方法をまとめた内容です。Python3.10から入った機能がいくつかあります。

いくつかPythonでtypingを使って型指定する記事について書いてるのでそちらも見ていただければと思います!

取りうる値の範囲を指定できるLiteral型 – Python3.8から


Python3.8から入った機能。

Literal[取りうる値1, 取りうる値2]という感じで指定できる。Literal型の変数に指定していない値を入れようとした場合はエディタが怒ってくれる。

https://docs.python.org/ja/3/library/typing.html#typing.Literal

TypeScriptのunionみたいなイメージ。

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

from dataclasses import dataclass
from typing import Literal

@dataclass
class TaskInfo:
  job_id: str
  task_status: Literal["ok", "failed", "canceled"]

TaskInfo(task_status="ok", job_id="test_id")
TaskInfo(task_status="hoge", job_id="test_id")  # これはエディタに怒られる

TypeGuardで型ガード – Python3.10から


Python3.10から入った新しい機能。

関数の戻り値の型にTypeGuard[型]を指定することで、引数が指定した型であることをエディタに認識させることができます。

https://www.python.jp/news/wnpython310/userdefinedtypegurd.html#%E5%9E%8B%E3%81%AE%E7%B5%9E%E3%82%8A%E8%BE%BC%E3%81%BF%E3%81%A8%E5%9E%8B%E3%82%AC%E3%83%BC%E3%83%89

TypeScriptの<arg> is <Type>みたいなイメージ。

https://typescript-jp.gitbook.io/deep-dive/type-system/typeguard#yznotype-guard

from typing import TypeGuard, TypedDict


class ErrorRes(TypedDict):
  error_code: str
  message: str

class SuccessRes(TypedDict):
  status: int
  message: str

def is_error_res(v: dict) -> TypeGuard[ErrorRes]:
  return v.get("error_code") is not None


response = {
  "error_code": "eee",
  "message": "invalid parameters"
}

# if内はresponseはErrorRes型であることをエディタが認識する
if is_error_res(response):
  print(response["error_code"])  # エディタが"error_code"キーを補完してくれる
  print(response["status"])  # エディタに怒られる

TypeAliasで型に別名をつける – Python3.10から


Python3.10から入った機能。

<型名>: TypeAlias = <別名つけたい型>という形式で型に別名をつけられる。

https://www.python.jp/news/wnpython310/typealias.html

from typing import TypeAlias

JobId: TypeAlias = str


def cancel_job(job_id: JobId):
  # キャンセル処理
  pass

cancel_job("job_id")
cancel_job(12)  # これだとエディタに怒られる

TypedDictで辞書dictに型をつける – Python3.8から


Python3.8から追加。

TypedDictを継承したクラスを指定するとdictでも型を間違えているとエディタが怒ってくれるようになる。

https://docs.python.org/ja/3/library/typing.html#typing.TypedDict

また、TypedDictを継承したクラスを継承したクラスもTypedDictとして使える。

from typing import TypedDict

class Person(TypedDict):
  name: str
  age: int

# Personを継承したStudentもTypedDictになる
class Student(Person):  
  grade: int

class Teacher(Person):
  salary_by_month: int

d: Person = {
  "name": 12,  # 型が違うのでエディタに怒られる
  "age": 12
}

del d["hoge"]  # 存在しないキーなのでエディタに怒られる


s: Student = {
  "grade": 123,
  "name": "hoge",
  "age": 12
}

コメントを残す

メールアドレスが公開されることはありません。