typescript - T が Record を拡張すると、keyof T は型として ,string を与えません

okwaves2024-01-25  13

私は次のことを達成しようとしています:

type MyFormProps<FieldName extends keyof FormShape, FormShape extends Record<string, any>> = {
  id: string;
  value: FormShape[FieldName];
}

const formPropsBuilder = <FieldName extends keyof FormShape, FormShape extends Record<string, any>>(
  name: FieldName,
  form: FormShape,
): MyFormProps<FieldName, FormShape> => {
  return {
    id: name,
    value: form[name],
  }
}

しかし、名前が文字列型であるというエラーが表示されます |番号 |シンボル。

FormShape は Record<string, any> を拡張するため、そのキーは文字列である必要があるため、これは奇妙です。

それは普通ですか? もしそうなら、それを機能させる方法はありますか?

ありがとう ;)

プレイグラウンドへのリンク: https://www.typescriptlang.org/play?#code/C4TwDgpgBAsiBiB7ATgWwArMWAzgHngEsIAbAEwDkBDVACAD2AgDsycoBrCERAMyiRoAygAsqkADQCUqUeLqMWbKACUIAYxRk8OYMkLMA5lKrMQAPnNQAvFADeAKChRCZAFxRd+owG4nU ADcqEgBXCA9BWTFIAG0iUkoaCABdPwBfBwdNZl0oXhlMbBwAIRDCcghkGygCYnJqWigGJlZ2Lh5+SLlJaWFohRblNU1kbS8DYyhTC3MACn9mJIi6xNoJf3y0CJluiHWASg84SMLcWoSGvd6o+StrK0dnZAhg EORme39nVw9Fta-AsEwh5NqgYn8UutnBk0kA



------------------------

文字列のインデックスタイプは 3 種類あると思います |番号 |シンボルなので、それに割り当てるには、上記と同じタイプの ID を作成する必要がある場合があります。

type MyFormProps = {
  id: string | number | symbol;
}

または、入力が常に文字列であると思われる場合は、型を文字列としてキャストすることもできます。

const formPropsBuilder = <K extends keyof T, T extends Record<string, any>>(name: K): MyFormProps => {
  return {
    id: name as string,    
  }
}
``



------------------------

これも奇妙なことに気づきました。私の回避策は次のとおりです。

type StringKey<T extends Record<string, any>> = keyof T extends string
  ? keyof T
  : never

これで、StringKey<Record<string, any>> が完成しました。文字列を拡張します。

1

Extract<T, string> を実行することもできます。

– スモールノイド

2022 年 10 月 24 日 19:52



------------------------

ジェネリック型を追加する理由はありますか?これを次のように単純化します。

type MyFormProps = {
  id: string;
}

const formPropsBuilder = <FieldName extends keyof Record<string, any>>(name: FieldName): MyFormProps => {
  return {
    id: name,
  }
}

この単純化によりエラーはなくなります。

3

1

フィールド名がレコードのキーを拡張する場合<文字列、任意>この場合、FieldName は文字列になります (これ以上の制約はありません)。そもそもなぜジェネリックを使用するのでしょうか?

– 浪費家

2020 年 9 月 3 日 10:56

ああ、申し訳ありませんが、これは良い点です。私の例は不完全です。 FieldName は FormShape を拡張し、FormShape は Record<string, any> を拡張しますが、明確に定義された辞書である可能性があります。オーバーしました

– ピエール・プーパン

2020 年 9 月 3 日 11:35

例をより意味のあるものにするために投稿を編集しました。

– ピエール・プーパン

2020 年 9 月 3 日 11:41

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。