あるオブジェクトのこのフィールドを書き換えたいことあるでしょ。
type A: { x: X // => Yにしたい!!! }
まあこういうときはA2 extends A
みたいなのを宣言するか,まあいろいろやりようはあると思うんですが,これがネストしてたりするわけですよ。5重とかに。毎回extends
とか書きたくないし,そのためにimport
したりinterface
宣言みたいなのは書きたくない。宣言おことわり宣言。
そこでこういうのを作りました。先日のやつの焼き直しです。
// Tオブジェクトのプロパティキーのうち,Kを除いたものを返す。 // NotKeys<{ x: X, y: Y, z: Z }, "y"> === "x" | "z" になる type NotKeys<T, K> = { [P in keyof T]: P extends K ? never : P; }[keyof T]; // TオブジェクトからKプロパティを落とす型 // type OmitKey<T, K> = Pick<T, Extract<keyof T, NotKeys<T, K>>>; // 良く見たらExtract不要だった type OmitKey<T, K> = Pick<T, NotKeys<T, K>>; // TオブジェクトからKキーを落としてから,Kキーの型がTTになっているオブジェクト型を作って,合体させる type Modified<T, K extends string, TT> = OmitKey<T, K> & Record<K, TT> type X = string; type X2 = boolean; type Y = number; interface A { x: X, y: Y }; interface B { x: X, y: Y } interface T { a: A, b: B } type T2 = Modified<T, "a", Modified<A, "x", X2>> const t: T = { a: { x: "123", y: 123 }, b: { x: "123", y: 123 } } const t2: T2 = { a: { x: true, y: 123 }, b: { x: "123", y: 123 } }
これのイケてるところは,ネストしていても内部の型を書き換えられることです。
これのイケてないところは,結局A
型の名前が出てきてしまうので,import A
不可避ということです。T
型からK
キーで取り出したプロパティの型は自明なので次のModified
に渡してやりたいのですが,複数の型引数を取る型に型を1つだけ渡す(型のcurrying),みたいなことができないっぽいので諦めます。
僕は型初心者なのでどうしたらよいかわからないです。