是否有方法更改*.d中定义的接口属性的类型?Ts在typescript中?
例如:
x.d.ts中的接口定义为
interface A {
property: number;
}
我想在我写入的typescript文件中改变它
interface A {
property: Object;
}
甚至这个也可以
interface B extends A {
property: Object;
}
这种方法有效吗?当我试我的系统时,它不工作。只是想确认一下有没有可能?
如果其他人需要一个通用的实用程序类型来做到这一点,我提出了以下解决方案:
/**
* Returns object T, but with T[K] overridden to type U.
* @example
* type MyObject = { a: number, b: string }
* OverrideProperty<MyObject, "a", string> // returns { a: string, b: string }
*/
export type OverrideProperty<T, K extends keyof T, U> = Omit<T, K> & { [P in keyof Pick<T, K>]: U };
我需要这个,因为在我的例子中,覆盖的关键是一个泛型本身。
如果没有准备好省略,请参阅从类型中排除属性。
有趣的是,我花了一天的时间调查解决同一个案子的可能性。
我发现这样做是不可能的:
// 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个,以避免愚蠢的情况
如果你只想修改一个现有属性的类型,而不是删除它,那么&就足够了:
// Style that accepts both number and percent(string)
type BoxStyle = {
height?: string | number,
width?: string | number,
padding?: string | number,
borderRadius?: string | number,
}
// These are both valid
const box1: BoxStyle = {height: '20%', width: '20%', padding: 0, borderRadius: 5}
const box2: BoxStyle = {height: 85, width: 85, padding: 0, borderRadius: 5}
// Override height and width to be only numbers
type BoxStyleNumeric = BoxStyle & {
height?: number,
width?: number,
}
// This is still valid
const box3: BoxStyleNumeric = {height: 85, width: 85, padding: 0, borderRadius: 5}
// This is not valid anymore
const box4: BoxStyleNumeric = {height: '20%', width: '20%', padding: 0, borderRadius: 5}
注意:不确定我在这个答案中使用的语法是否可用,当写旧的答案时,但我认为这是解决这个问题中提到的例子的更好方法。
我有一些与这个主题相关的问题(覆盖接口属性),这是我如何处理它:
首先创建一个泛型接口,其中包含您想要使用的可能类型。
您甚至可以为通用参数使用选择默认值,如<T extends number | SOME_OBJECT = number>中所示
type SOME_OBJECT = { foo: "bar" }
interface INTERFACE_A <T extends number | SOME_OBJECT = number> {
property: T;
}
然后你可以根据该契约创建新类型,通过将一个值传递给泛型参数(或省略它并使用默认值):
type A_NUMBER = INTERFACE_A; // USES THE default = number TYPE. SAME AS INTERFACE_A<number>
type A_SOME_OBJECT = INTERFACE_A<SOME_OBJECT> // MAKES { property: SOME_OBJECT }
这就是结果:
const aNumber: A_NUMBER = {
property: 111 // THIS EXPECTS A NUMBER
}
const anObject: A_SOME_OBJECT = {
property: { // THIS EXPECTS SOME_OBJECT
foo: "bar"
}
}
打印稿操场
覆盖为别名类型
你可以使用这个类型的别名:
type Override<T, K extends { [P in keyof T]: any } | string> =
K extends string
? Omit<T, K>
: Omit<T, keyof K> & K;
在下面的语法中使用alike:
全球接口
interface IFirst {
username: string;
}
接口由重写只是名称
interface ISecond extends Override<IFirst, 'username'> {
username: number;
}
类型别名覆盖
type IThird = Override<IFirst, { username: boolean }>;
编辑:
我试图通过将问题作为建议发送到typescript Repo,将这个别名类型添加为typescript中的内置类型