今日のタブ記事
Next.js + MDX でブログを書いていますを読んだ。
Next.jsと、MDXというマークダウンの中にJSXを書けるフォーマットでブログを作った話。
MDX、ぱっと見てみると頭がこんがらがる……!(以下記事から引用)
import Button from '../components/button.js'
# MDX + Next.js
Look, a button! 👇
<Button>👋 Hello</Button>
import文を見た瞬間に頭がJSXだと認識するけど、次の行の#
で「あれ、このコメントの方式はRubyだったような……?」みたいな感じでバグってしまうし、3行目の通常の文章が逆に異質に見えてしまう。
でもこれ慣れたら便利そうだな〜と思い、日付を見たら2019年の記事だった。2019年でNext.jsを使ってブログを作ってるってすごいなあ。
TypeScriptのプリミティブ型の大文字と小文字
たとえば、
const moji: string = 'hoge'
みたいな感じで型をつけるときってstring
と小文字で書く場合もあれば、Vueのpropsを定義するときに
props: {
moji: {
type: String,
default: 'hoge
},
}
みたいにString
と最初だけ大文字のときもある。
これは一体なんぞや……どっちをどのタイミングで使えばいいんだ?となり調べてみた。
タイプスクリプトのプリミティブ型というちょっと怪しい翻訳の記事がヒットしたので読んでみたら、
JavaScriptコードで適切に使用されることはほとんどない非プリミティブボックスオブジェクトを参照します。(引用)
と書いてあり、非プリミティブボックスオブジェクト?というよくわからない言葉が出てきたので調べたところ、ラッパーオブジェクトなるものがあることが分かった。
ラッパーオブジェクト
jsprimerのラッパーオブジェクトによると、
- Boolean, Number, String, Symbolにはそれぞれ対応するオブジェクトが存在する
- それぞれのオブジェクトをnewすることでそのオブジェクトのインスタンスを使える
- たとえばStringなら
const str = new String("hoge")
str.toUpperCase() // => "HOGE"
- 上記のように、プリミティブ型のオブジェクトをインスタンス化すると、「そのプリミティブ型の値を包んだオブジェクト」ができあがる
- これを「その型の値を包んだオブジェクト」ということでラッパーオブジェクトと呼ぶ
- nullとundefinedにはラッパーオブジェクトは存在しない
- ラッパーオブジェクトは名前の通りObject型で、typeofを使うとobjectになる。
const str = "hoge"
console.log(typeof str) // => "string"
const str2 = new String("hoge")
console.log(typeof str2) // => "object"
自動変換
プリミティブ型の値に対してプロパティアクセスをすると自動的にラッパーオブジェクトに変換されるらしい。
つまり、
const str = "hoge"
str.toUpperCase() // <= ここでラッパーオブジェクトに変換されてるのでプロパティアクセスできる
// (new String(str)).toUpperCase() と同じらしい
逆に、ラッパーオブジェクトから値を取り出すときはvalueOf
を使うらしい。
const strObj = new String("hoge")
console.log(strObj.valueOf()) // => "hoge"
こんな感じで、プリミティブな値 <=> ラッパーオブジェクトの変換は自動でやってくれている。
どっちを使うほうがいいかは、基本的にリテラルを使ったプリミティブな値を使ったほうがいいということらしい。理由は
- 必要に応じてプリミティブな値からラッパーオブジェクトに変換される
- ラッパーオブジェクトを常に使う利点がない
- typeofの評価がobjectになるため混乱する
まあ実際に自動で変換してくれるなら、使いたいプロパティにアクセスするまで全てのプロパティを内包する必要もなさそうだしなるほどといった感じ。
で、結局
そういえば大文字と小文字の使いわけの話だったのに全然違う話になってしまった。
自分でふと考えたけど、Vueのpropsに渡すときは{ type: String }
で、これは別に「TypeScriptの構文ではなくてObjectのvalueとしてString
を渡している」ということだと思う。
{ type: string }
と書いたら構文エラーになったけど、'string' only refers to a type, but is being used as a value here.Vetur(2693)
というエラーを見るに「型を参照したいのに値を渡してるぞ」みたいな感じっぽいので、Vue側で受け取る値の型定義的なものだと思う。
ちなみに{ type: Stirng as PropType<string>}
だといけた。えぇ……
Composition APIにするときにOptions APIのpropsの定義方法をガラリと崩したら混乱するからあんま変えないでおこう、でもPropTypesというやつで拡張できるようにしよう、という感じなんだろうか。
悩み
- コードを読むスピードが遅い
- コードを読んで理解してもすぐ忘れる
- 仕様理解はどうすれば進むのか
- 仕様は全部メモらないと忘れる
みたいな悩みがある。
そもそもプロダクトの仕様理解がなかなかうまく効率的にできなくて、実装中にわからなくなって手が止まって……みたいな感じで実装スピードに影響が出る。
もしかして仕様をコード読んだりプロダクトを触ったりして全て網羅して言語化しておくしかないのだろうか。
頭が悪すぎて単に理解力がないというだけなのだろうか……。
今のチームに入って間もないのだけど、仕様理解が全然進まないので一回時間を取って仕様を全部書き出すようなことをやってみようかと思うんだけど、それが効率の悪いやり方だとしたらと思うと手が動かない。
誰か助けて。