覆盖 Typescript d.ts 文件中定义的接口属性类型

IT技术 javascript typescript typescript-typings
2021-01-29 11:44:57

有没有办法改变*.d.tstypescript中定义的接口属性的类型

例如:一个接口x.d.ts定义为

interface A {
  property: number;
}

我想在我写入的typescript文件中更改它

interface A {
  property: Object;
}

甚至这也行

interface B extends A {
  property: Object;
}

这种方法会奏效吗?当我在我的系统上尝试时它不起作用。只是想确认是否有可能?

6个回答

我使用一种首先过滤字段然后组合它们的方法。

引用从类型中排除属性

interface A {
    x: string
}

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

对于接口:

interface A {
    x: string
}

interface B extends Omit<A, 'x'> {
  x: number
}
扩展界面正是我想要的,谢谢!
2021-03-22 11:44:57
很高兴知道这一点。但问题是它仍然没有修改现有的。
2021-03-24 11:44:57
注意:您需要上面的 typescript 3.5.3 才能使用它。
2021-03-28 11:44:57
这正是我正在寻找的。这就是我期望typescriptextend默认工作的方式,但唉,这个小问题Omit解决了一切🙌
2021-04-05 11:44:57
节省我的时间!谢谢👍
2021-04-12 11:44:57
 type ModifiedType = Modify<OriginalType, {
  a: number;
  b: number;
}>
 
interface ModifiedInterface extends Modify<OriginalType, {
  a: number;
  b: number;
}> {}

ZSkycat extends Omit解决方案的启发,我想出了这个:

type Modify<T, R> = Omit<T, keyof R> & R;

// before typescript@3.5
type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

例子:

interface OriginalInterface {
  a: string;
  b: boolean;
  c: number;
}

type ModifiedType  = Modify<OriginalInterface , {
  a: number;
  b: number;
}>

// ModifiedType = { a: number; b: number; c: number; }

一步一步来:

type R0 = Omit<OriginalType, 'a' | 'b'>        // { c: number; }
type R1 = R0 & {a: number, b: number }         // { 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: number; c: number; }

TypeScript 实用程序类型


v2.0 深度修改

interface Original {
  a: {
    b: string
    d: {
      e: string // <- will be changed
    }
  }
  f: number
}

interface Overrides {
  a: {
    d: {
      e: number
      f: number // <- new key
    }
  }
  b: {         // <- new key
    c: number
  }
}

type ModifiedType = ModifyDeep<Original, Overrides>
interface ModifiedInterface extends ModifyDeep<Original, Overrides> {}
// ModifiedType =
{
  a: {
    b: string
    d: {
      e: number
      f: number
    }
  }
  b: {
    c: number
  }
  f: number
}

ModifyDeep 在下面找到

@Dominic 好点,我已经更新了答案。两个同名的接口可以合并。typescriptlang.org/docs/handbook/...
2021-03-18 11:44:57
@Donnovan 这是自定义类型,再次查看答案找到-> type Modify<T, R> = Omit<T, keyof R> & R;
2021-04-04 11:44:57
菜鸟在这里,但您在示例中从接口更改为类型,不是吗?或者没有区别?
2021-04-11 11:44:57
这是一个很好的解决方案。
2021-04-13 11:44:57
Niceeeeeeeeeee :D
2021-04-13 11:44:57

您无法更改现有属性的类型。

您可以添加一个属性:

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'.
反对将 Java 称为“其他语言”
2021-03-23 11:44:57
@wvdz 并不是说​​我很在意否决票,但是你在说什么?哪里有人甚至提到了java?搜索“java”页面只有一个发现,它在您的评论中。
2021-03-23 11:44:57
使用 Typescript >=1.1 通过扩展接口覆盖方法类型,您需要包含原始接口中的所有方法,否则您将收到类型不兼容的错误,请参阅github.com/Microsoft/TypeScript/issues/978
2021-03-24 11:44:57
您可以先忽略要覆盖的值,然后重新定义它们,我们可以让 @ZSkycat 的答案成为解决方案吗?
2021-03-30 11:44:57
oop,对不起,我的错。Tbh,即使是你的话,我真的只是有点脾气暴躁。不幸的是不能再删除downvote了。
2021-04-06 11:44:57

稍微扩展@zSkycat 的答案,您可以创建一个泛型,它接受两种对象类型并返回一个合并类型,其中第二个的成员覆盖第一个的成员。

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;
非常酷:-) 我之前用 Omit 用一两个属性完成了这个,但这更酷:-) 我经常想“扩展”一个服务器实体类型,并在客户端更改一些需要或可选的东西.
2021-03-18 11:44:57
这应该是现在公认的解决方案。“扩展”界面的最简洁方法。
2021-04-05 11:44:57

Omit 扩展接口时的属性:

interface A {
  a: number;
  b: number;
}

interface B extends Omit<A, 'a'> {
  a: boolean;
}