web-dev-qa-db-ja.com

TypeScript d.tsファイルで定義されたインターフェイスプロパティタイプのオーバーライド

Typescriptの*.d.tsで定義されているインターフェイスプロパティのタイプを変更する方法はありますか?

例:x.d.tsのインターフェースは次のように定義されます

interface A {
  property: number;
}

書き込み先のTypeScriptファイルで変更したい

interface A {
  property: Object;
}

またはこれでも動作します

interface B extends A {
  property: Object;
}

このアプローチは機能しますか?私のシステムで試してもうまくいきませんでした。可能かどうか確認したいだけですか?

48
Abdul23

既存のプロパティのタイプを変更することはできません。

プロパティを追加できます:

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'.
25
Nitzan Tomer

最初にフィールドをフィルタリングしてからそれらを結合する方法を使用します。

参照 タイプからプロパティを除外

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

インターフェイス用:

interface A {
    x: string
}

interface B extends Omit<A, 'x'> {
  x: number
}
49
ZSkycat
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; }
24
Qwerty

@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;
21
ryanjduffy

同じケースを解決する可能性を調査するのに一日費やしています。この方法ではできないことがわかりました。

// 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個に減らします

3
Egor Malkevich