🍧

「foo?: string」と「bar: string | undefined」の違い

2024/02/10に公開4
type Hoge = {
  foo?: string;
  bar: string;
}

上記のfoobar2つのプロパティの書き方ですが、
どちらもOptionalな値で同じ意味になるかと思っていましたが、
どうやら違ったよう。勘違いしていた・・🙄

違いは下記の通り。
Objectの初期作成時に省略できるかどうかが違うよう。

省略 undefinedの代入
foo?: string [1]
bar: string | undefined

bar: string | undefinedは省略できないので、
「プロパティ 'bar' は型 '{}' にありませんが、型 'Hoge' では必須です。」というTypeエラーが発生する。

type Hoge = {
  foo?: string;
  bar: string | undefined;
}

const huga: Hoge = {}
// エラー:プロパティ 'bar' は型 '{}' にありませんが、型 'Hoge' では必須です。

ReactのPropsの型定義でも同様。
fooは省略できるが、barはできないのでTypeエラーが発生する。

type Hoge = {
  foo?: string
  bar: string | undefined
}

const Child = ({ foo, bar }: Hoge) => {
  // 中略
}

export const Parent = () => {
  return <Child />  // プロパティ 'bar' は型 '{}' にありませんが、型 'Hoge' では必須です。
}
脚注
  1. tsconfigのexactOptionalPropertyTypesプロパティで、undefinedの代入を禁止することも可能です。 ↩︎

Discussion

Honey32Honey32

(参考までに) TypeScript の exactOptionalPropertyTypes というオプションが true になっているときに、このような違いが出ます。

何も設定しないときには false なので、おそらく tsconfig.json で有効になっている (あるいはこのオプションを有効にするルールを extend している)のだと思います。

Honey32Honey32

ホントだ! | undefined なプロパティは省略不可能なのはオプション関係無かったですね...

失礼しました 🙇‍♂

poupou

いえいえ、コメントありがたいです。
undefinedの代入の可否については、
exactOptionalPropertyTypesで変わる旨を注釈いれてみました🤭