使打字稿接口扩展另一个接口,不包括已定义的键
Make typescript interface extend another interface excluding keys already defined
对于我的 iPhone 上的一些 hacky 脚本( 不是 我会为生产编写的代码),我经常发现自己将 string
视为 string[]
(字符数组)。由于在 phone 上打字比在键盘上打字慢得多,而且考虑到 57 个字符宽的屏幕尺寸,字符非常宝贵,因此我编写了一些代码,采用 Array.prototype
的所有方法,将其映射到Array.from(this)[fn]
,并将其附加到 String.prototype
(如果尚不存在)。比如我要.slice()
还是return一个string
,而不是string[]
.
Object.entries(
Object.getOwnPropertyDescriptors(Array.prototype)
)
.filter(([n, d]) =>
!(n in String.prototype) &&
typeof d.value === 'function'
)
.forEach(([n]) =>
String.prototype[n] = function (...args) {
return Array.from(this)[n](...args)
}
)
现在我可以 运行 'abc'.filter(x => x !== 'b')
并接收 ['a', 'c']
。万岁。
现在我想编写更新后的 interface String
而无需手动复制 Array<T>
中的每个有效声明。 (有时 play.js 会读取 .d.ts
文件。)
我最好的尝试是引入循环类型引用,这并不让我感到惊讶。
type MethodNames<T> = {
[K in keyof T & string]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T & string];
type MethodsOf<T> = {
[K in MethodNames<T>]: T[K];
};
type CharArray = Omit<MethodsOf<Array<string>>, keyof string>;
declare global {
interface String extends CharArray {}
}
export {};
直到我 String
扩展 CharArray
,一切正常。 CharArray
有正确的方法。添加扩展后,CharArray
会尝试排除它自己的成员,因为这些成员现在是 String
.
的成员
我问的可能吗?我怀疑答案是否,但我想我会问。
在发布这个问题前几秒钟,我想到了一个主意,而且它奏效了。与其排除 keyof string
(Omit
所做的),不如让 CharArray
使用 string[K]
(如果存在)。
type CharArray = {
[K in MethodNames<Array<string>>]: K extends keyof string ? string[K] : Array<string>[K];
};
现在,虽然引擎 可以 争论循环引用,但它只是将 string
的属性与其自身合并,所以它并不关心。 (至少,我认为是这个原因。)
对于我的 iPhone 上的一些 hacky 脚本( 不是 我会为生产编写的代码),我经常发现自己将 string
视为 string[]
(字符数组)。由于在 phone 上打字比在键盘上打字慢得多,而且考虑到 57 个字符宽的屏幕尺寸,字符非常宝贵,因此我编写了一些代码,采用 Array.prototype
的所有方法,将其映射到Array.from(this)[fn]
,并将其附加到 String.prototype
(如果尚不存在)。比如我要.slice()
还是return一个string
,而不是string[]
.
Object.entries(
Object.getOwnPropertyDescriptors(Array.prototype)
)
.filter(([n, d]) =>
!(n in String.prototype) &&
typeof d.value === 'function'
)
.forEach(([n]) =>
String.prototype[n] = function (...args) {
return Array.from(this)[n](...args)
}
)
现在我可以 运行 'abc'.filter(x => x !== 'b')
并接收 ['a', 'c']
。万岁。
现在我想编写更新后的 interface String
而无需手动复制 Array<T>
中的每个有效声明。 (有时 play.js 会读取 .d.ts
文件。)
我最好的尝试是引入循环类型引用,这并不让我感到惊讶。
type MethodNames<T> = {
[K in keyof T & string]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T & string];
type MethodsOf<T> = {
[K in MethodNames<T>]: T[K];
};
type CharArray = Omit<MethodsOf<Array<string>>, keyof string>;
declare global {
interface String extends CharArray {}
}
export {};
直到我 String
扩展 CharArray
,一切正常。 CharArray
有正确的方法。添加扩展后,CharArray
会尝试排除它自己的成员,因为这些成员现在是 String
.
我问的可能吗?我怀疑答案是否,但我想我会问。
在发布这个问题前几秒钟,我想到了一个主意,而且它奏效了。与其排除 keyof string
(Omit
所做的),不如让 CharArray
使用 string[K]
(如果存在)。
type CharArray = {
[K in MethodNames<Array<string>>]: K extends keyof string ? string[K] : Array<string>[K];
};
现在,虽然引擎 可以 争论循环引用,但它只是将 string
的属性与其自身合并,所以它并不关心。 (至少,我认为是这个原因。)