是否有方法更改*.d中定义的接口属性的类型?Ts在typescript中?

例如: x.d.ts中的接口定义为

interface A {
  property: number;
}

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

interface A {
  property: Object;
}

甚至这个也可以

interface B extends A {
  property: Object;
}

这种方法有效吗?当我试我的系统时,它不工作。只是想确认一下有没有可能?


当前回答

有趣的是,我花了一天的时间调查解决同一个案子的可能性。 我发现这样做是不可能的:

// 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;
}

默认保留some类型,当不需要重写时,允许自动完成工作。

Then

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

// @ts-ignore
interface B extends A {
    x: SomeOtherType;
}

在这里使用@ts-ignore标志禁用愚蠢的异常,告诉我们我们做错了什么。有趣的是,一切都按照预期进行。

在我的情况下,我减少了类型x的范围,它允许我做更严格的代码。例如,你有一个100个属性的列表,你把它减少到10个,以避免愚蠢的情况

其他回答

创建修饰符类型

type Modify<T, R extends {[P in keyof T]:any} > = Omit<T, keyof R> & R;

你可以

interface ModifiedInterface extends Modify<OriginalType, {
  a: number;
  b: number;
}> {}

它会给你一个类型自动完成

基于ZSkycat的出色回答,您可以创建一个抽象的Override泛型类型,该类型易于使用并清楚地解释了代码的意图。

type Override<T, K extends keyof T, N> =省略<T, K> & {[K中的K1]: N};

地点:

现有类型 K =您希望覆盖的类型的键 N =要覆盖现有类型的键的新类型

使用示例:

type GraphQLCodegenConfig =覆盖<CodegenConfig, 'schema', DocumentNode>;

日期:19/3/2021。 我认为最新的typescript(4.1.2)版本支持d.ts文件中的接口覆盖。

// in test.d.ts

interface A {
  a: string
}

export interface B extends A {
  a: number
}

// in any ts file
import { B } from 'test.d.ts'

// this will work
const test: B = { a: 3 }

// this will not work
const test1: B = { a: "3" }

稍微扩展一下@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;

不能更改现有属性的类型。

你可以添加一个属性:

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类型是使用现有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'.