Typescriptの*.d.ts
で定義されているインターフェイスプロパティのタイプを変更する方法はありますか?
例:x.d.ts
のインターフェースは次のように定義されます
interface A {
property: number;
}
書き込み先のTypeScriptファイルで変更したい
interface A {
property: Object;
}
またはこれでも動作します
interface B extends A {
property: Object;
}
このアプローチは機能しますか?私のシステムで試してもうまくいきませんでした。可能かどうか確認したいだけですか?
既存のプロパティのタイプを変更することはできません。
プロパティを追加できます:
interface A {
newProperty: any;
}
ただし、既存のタイプの変更:
interface A {
property: any;
}
エラーになります:
後続の変数宣言は同じ型でなければなりません。変数 'property'は型 'number'でなければなりませんが、ここでは型 'any'を持っています
もちろん、既存のインターフェースを拡張する独自のインターフェースを使用できます。その場合、型を互換性のある型にのみオーバーライドできます。次に例を示します。
interface A {
x: string | number;
}
interface B extends A {
x: number;
}
ところで、おそらくObject
を型として使用することは避け、代わりにany
型を使用する必要があります。
any
タイプのドキュメント には次のように記載されています。
Anyタイプは、既存のJavaScriptを操作する強力な方法であり、コンパイル中にタイプチェックを徐々にオプトインおよびオプトアウトできます。他の言語と同じように、Objectが同様の役割を果たすことを期待するかもしれません。 しかし、Object型の変数は、値を割り当てることしかできません-実際に存在するものであっても、それらの任意のメソッドを呼び出すことはできません:
let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
最初にフィールドをフィルタリングしてからそれらを結合する方法を使用します。
interface A {
x: string
}
export type B = Omit<A, 'x'> & { x: number };
インターフェイス用:
interface A {
x: string
}
interface B extends Omit<A, 'x'> {
x: number
}
type ModifiedType = Modify<OriginalType, { a: number; b: number; }>
ZSkycat'sextends Omit
ソリューションに触発されて、私はこれを思いつきました:
type Modify<T, R> = Omit<T, keyof R> & R; // before [email protected] type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R
例:
interface OriginalType {
a: string;
b: boolean;
c: number;
}
type ModifiedType = Modify<OriginalType , {
a: number;
b: number;
}>
// ModifiedType = { a: number; b: number; c: number; }
段階的に進む:
type T0 = Exclude<'a' | 'b' | 'c' , 'a' | 'b'> // 'c'
type T1 = Pick<OriginalType, T0> // { c: number; }
type T2 = T1 & {a: number, b: number } // { a: number; b: boolean; c: number; }
@zSkycatの答えを少し拡張すると、2つのオブジェクトタイプを受け入れ、2番目のメンバーが最初のメンバーをオーバーライドしたマージタイプを返すジェネリックを作成できます。
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;
interface A {
name: string;
color?: string;
}
// redefine name to be string | number
type B = Merge<A, {
name: string | number;
favorite?: boolean;
}>;
let one: A = {
name: 'asdf',
color: 'blue'
};
// A can become B because the types are all compatible
let two: B = one;
let three: B = {
name: 1
};
three.name = 'Bee';
three.favorite = true;
three.color = 'green';
// B cannot become A because the type of name (string | number) isn't compatible
// with A even though the value is a string
// Error: Type {...} is not assignable to type A
let four: A = three;
同じケースを解決する可能性を調査するのに一日費やしています。この方法ではできないことがわかりました。
// a.ts - module
export interface A {
x: string | any;
}
// b.ts - module
import {A} from './a';
type SomeOtherType = {
coolStuff: number
}
interface B extends A {
x: SomeOtherType;
}
原因モジュールは、アプリケーションで使用可能なすべてのタイプを認識していない場合があります。そして、それはどこからでもすべてを退屈に移植し、このようなコードを実行しています。
export interface A {
x: A | B | C | D ... Million Types Later
}
オートコンプリートを適切に機能させるには、後でタイプを定義する必要があります。
だからあなたは少しカンニングをすることができます:
// a.ts - module
export interface A {
x: string;
}
オーバーライドが不要な場合、オートコンプリートが機能するように、デフォルトでいくつかのタイプを残しました。
それから
// b.ts - module
import {A} from './a';
type SomeOtherType = {
coolStuff: number
}
// @ts-ignore
interface B extends A {
x: SomeOtherType;
}
@ts-ignore
フラグを使用して、ここで愚かな例外を無効にします。そして、おもしろいことはすべて期待どおりに機能します。
私の場合、タイプx
のスコープビジョンを減らしています。これにより、コードをより厳密に実行できます。たとえば、100個のプロパティのリストがあり、愚かな状況を避けるために10個に減らします