結論としてカスタム属性を使います。
JSX上でinputタグ(type="radio")とlabelの擬似要素を組み合わせた際に実際にクリックされる方であるlabelタグの属性にnameやvalueを使えずつまづいたので代替え方法のTIPSです。
背景
ご存知のようにinput + labelのスタイル制御はJSを使わずに選択されたラベルのスタイルを変更するHTML/CSSでこれまで使われきた手法です。
わざわざReactでこのテクニックを使ってしまったところlabelクリック時に状態を保存したいのですがlabelタグにnameやvalueといった属性は使えないためlabeタグに必要な情報を埋め込めなくなりました。
素直にJSオンリーでスタイル制御すべきだった...
nameやvalueをlabelタグへそのまま使うと当然のようにそんな属性の型はねえぞと怒られる。
Type '{ children: string; onClick: (e: MouseEvent<HTMLLabelElement, MouseEvent>) => void; value: string | number; id: string; htmlFor: string; }' is not assignable to type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'.
Property 'value' does not exist on type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'.ts(2322)
もうCSSでスタイルを当ててしまったあとだし作り変えるための優先順位はそこまで高くないしということでこのままlabelで使えるようにしました。同じような人はどうぞ。
解決策:カスタム属性を使う
といっても解決策は単純でnameやvalueに変わる属性を付与します。
<label data-{任意の名前} >Hello 沼!</label>
というようにカスタム属性を使います。
<label onClick={e => handleClickChange(e)} data-name={name} data-value={value}
htmlFor={idName} >Hello 沼!</label>
引っ張る際には e.currentTarget.dataset.{任意のカスタムデータ名} で引っ張れます。接頭辞のdata-は不要ですが。
そしてTypeScriptとしてアサーションを使うのは御行儀がよくないのですが下のような形で引っ張ってこれました。
const handleClickChange = (e: MouseEvent): void => {
const name = (e.currentTarget as HTMLInputElement).dataset.name as string;
const value = (e.currentTarget as HTMLInputElement).dataset.value;
setProfile(currentValue => ({
...currentValue,
[name]: value
}));
}