質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

2回答

1835閲覧

似ているオブジェクト間の変換処理方法について

m0a

総合スコア708

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2017/10/12 09:10

編集2017/10/13 06:58

以下のコードのように大部分のプロパティが同じで一部のみ異なるオブジェクト間で
変換処理を行いたいと考えております。

interface Base { a: number b: string dontUse: string } interface Convert { a: number b: string c: string } let base: Base = { a: 1, b: '2', dontUse: 'DontUse' } delete base.dontUse; let convert: Convert { // <-- error発生箇所 ...base, c: 'sample', } console.log(convert);

上記コードは変換したjsは想定通りに動きますがTypeScriptとしては以下のようなエラーが出ます。

Type '{ c: string; a: number; b: string; dontUse: string; }' is not assignable to type 'Convert'. Object literal may only specify known properties, and 'dontUse' does not exist in type 'Convert'.

今回は簡易版ですが、a,bのようなメンバが大量にあるのでできるだけ上記のような書き方をしたいのですが
良い方法はないでしょうか?

型キャストで無理矢理な変換ですとBaseやConvertに変更があった場合に、コンパイルエラーにならないため
それは避けたいと考えています。

イメージですが以下のようなコードが書けると一番嬉しいんです。

interface Base { a: number b: string dontUse: string } type Convert = { [P in keyof Base]: Base[P]; // want to delete from keyof Base 'dontUse' and add 'c' c: string; dontUse: undefined; } let base: Base = { a: 1, b: '2', dontUse: 'DontUse' } delete base.dontUse; let convert: Convert = { ...base, c: 'sample', } console.log(convert);

keyof でBaseのプロパティが取れるので、それに対してcを追加し dontUseを削除できれば一番綺麗だと思われます。

尚サンプルコードはこちらにおいています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

typescript

1function toConvert({ a, b }: { a: number, b: string }) { 2 return { ...{ a, b }, c: 'sample' }; 3}

こういう関数ではいかがですか?

投稿2017/10/13 08:07

yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m0a

2017/10/13 13:37

a,bのメンバが多数ある場合はしんどいので今回は使えなさそうです。ありがとうございました
guest

0

ベストアンサー

サンプルのケースではas Convertと型アサーションを使うとコンパイルエラーは無くなります。

typescript

1let convert: Convert = { 2 ...base, 3 c: 'sample', 4} as Convert;

(追記)Base型をベースにConvert型を定義する

TypeScriptでDiff型を表現する - Qiitaを参考に不要なプロパティを除いて継承してみました。共通部分のクラスを定義して継承した方がわかりやすそうな気がしますが。

typescript

1type DiffKey<T extends string, U extends string> = ( 2 & {[P in T]: P } 3 & {[P in U]: never } 4 & { [x: string]: never } 5)[T]; 6 7type Omit<T, K extends keyof T> = Pick<T, DiffKey<keyof T, K>>; 8 9interface Base { 10 a: number; 11 b: string; 12 dontUse: string; 13 dontUse2: string; 14} 15 16interface Convert extends Omit<Base, 'dontUse' | 'dontUse2'> { 17 c: string; 18} 19 20let convert: Convert = { 21 a: 1, 22 b: '2', 23 c: 'sample', 24}; 25console.log(convert); // { a: 1, b: '2', c: 'sample' } 26convert.dontUse = 'dontUse'; // compile error: 'dontUse' does not exist in type 'Convert'

投稿2017/10/12 11:06

編集2017/10/13 09:21
shimitei

総合スコア799

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m0a

2017/10/12 11:10

それですと、更にbaseに更に変更があった場合TypeScript側で検知できなくなりますよね。コンパイルエラー自体は必要なので、型キャスト以外の方法を探しています。
m0a

2017/10/12 11:19

簡単というワードが紛らわしかったかもしれません。追加情報を入れました。
m0a

2017/10/13 13:38

予想より複雑でしたが、上手くいきそうです。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問