Abd*_*l23 60 javascript typescript typescript-typings
有没有办法更改*.d.ts
intype中定义的接口属性的类型?
例如:接口in x.d.ts
定义为
interface A {
property: number;
}
Run Code Online (Sandbox Code Playgroud)
我想在我写的typescript文件中更改它
interface A {
property: Object;
}
Run Code Online (Sandbox Code Playgroud)
甚至这会起作用
interface B extends A {
property: Object;
}
Run Code Online (Sandbox Code Playgroud)
这种方法会起作用吗?当我尝试使用我的系统时,它无法正常工作.只是想确认它是否可能?
小智 65
我使用的方法首先过滤字段,然后将它们组合起来.
reference 从类型中排除属性
interface A {
x: string
}
export type B = Omit<A, 'x'> & { x: number };
Run Code Online (Sandbox Code Playgroud)
用于界面:
interface A {
x: string
}
interface B extends Omit<A, 'x'> {
x: number
}
Run Code Online (Sandbox Code Playgroud)
Qwe*_*rty 37
Run Code Online (Sandbox Code Playgroud)type ModifiedType = Modify<OriginalType, { a: number; b: number; }>
受ZSkycat extends Omit
解决方案的启发,我想到了这个:
Run Code Online (Sandbox Code Playgroud)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 OriginalType {
a: string;
b: boolean;
c: number;
}
type ModifiedType = Modify<OriginalType , {
a: number;
b: number;
}>
// ModifiedType = { a: number; b: number; c: number; }
Run Code Online (Sandbox Code Playgroud)
逐步进行:
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; }
Run Code Online (Sandbox Code Playgroud)
Nit*_*mer 33
您无法更改现有属性的类型.
您可以添加属性:
interface A {
newProperty: any;
}
Run Code Online (Sandbox Code Playgroud)
但改变一种现有的类型:
interface A {
property: any;
}
Run Code Online (Sandbox Code Playgroud)
导致错误:
后续变量声明必须具有相同的类型.变量'property'必须是'number'类型,但这里有'any'类型
您当然可以拥有自己的界面,扩展现有界面.在这种情况下,您只能将类型覆盖为兼容类型,例如:
interface A {
x: string | number;
}
interface B extends A {
x: number;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,你可能应该避免使用Object
类型,而是使用类型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'.
Run Code Online (Sandbox Code Playgroud)
rya*_*ffy 25
稍微扩展@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;
Run Code Online (Sandbox Code Playgroud)
JmJ*_*JmJ 24
Omit
扩展接口时的属性:
interface A {
a: number;
b: number;
}
interface B extends Omit<A, 'a'> {
a: boolean;
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*ian 24
覆盖接口的两个或多个属性的解决方案:
interface BaseInterface {
a: string;
b: string;
c: string;
}
interface ModifiedInterface extends Omit<BaseInterface, 'a' | 'b'> {
a?: string; // make it optional
b: boolean; // make it boolean
d: number; // add another property
}
Run Code Online (Sandbox Code Playgroud)
Mas*_*iri 11
对于像我这样懒惰的人的简短回答:
type Overrided = Omit<YourInterface, 'overrideField'> & { overrideField: <type> };
Run Code Online (Sandbox Code Playgroud)
我目前正在我的要点中构建一个更强大的解决方案,可以更好地处理数组并允许删除键或修改其?
可选性。
interface Original {\n x: {\n a: string\n b: string\n }\n}\n\ninterface Overrides {\n x: {\n a: never // <- this key will be deleted\n b?: string // <- this will become optional\n }\n}\n\n/* result = {\n x: {\n b?: string\n }\n} */ \n
Run Code Online (Sandbox Code Playgroud)\n*注意,版本 2 在此答案的历史记录中。
\ninterface Original {\n a: {\n a: string\n b: { a: string }\n c: string\n d: string // <- keep this one \n }\n}\n\ninterface Overrides {\n a: {\n a: { a: number } // <- overwrite string with object\n b: number // <- overwrite object with number\n c: number // <- overwrite string with number\n e: number // <- new property\n }\n}\n\ntype ModifiedType = ModifyDeep<Original, Overrides>\ninterface ModifiedInterface extends ModifyDeep<Original, Overrides> {}\n
Run Code Online (Sandbox Code Playgroud)\nconst example: ModifiedType = {\n a: {\n a: { a: number },\n b: number,\n c: number,\n d: string,\n e: number,\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\ntype ModifyDeep<A, B extends DeepPartialAny<A>> = {\n [K in keyof A | keyof B]: // For all keys in A and B:\n K extends keyof A // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n ? K extends keyof B // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80 key K exists in both A and B\n ? A[K] extends AnyObject // \xe2\x94\x82 \xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n ? B[K] extends AnyObject // \xe2\x94\x82 \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80 both A and B are objects\n ? B[K] extends AnyFunction // \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 Avoid deeply modifying functions which results in {}\n ? B[K] // \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x82\n : ModifyDeep<A[K], B[K]> // \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 We need to go deeper (recursively)\n : B[K] // \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 B is a primitive use B as the final type (new type)\n : B[K] // \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80 A is a primitive use B as the final type (new type) \n : A[K] // \xe2\x94\x9c\xe2\x94\x80 key only exists in A use A as the final type (original type) \n : B[K] // \xe2\x94\x94\xe2\x94\x80 key only exists in B use B as the final type (new type)\n}\n\ntype AnyObject = Record<string, any>\ntype AnyFunction = (...args: any[]) => any\n\n// This type is here only for some intellisense for the overrides object\ntype DeepPartialAny<T> = {\n /** Makes each property optional and turns each leaf property into any, allowing for type overrides by narrowing any. */\n [P in keyof T]?: T[P] extends AnyObject ? DeepPartialAny<T[P]> : any\n}\n
Run Code Online (Sandbox Code Playgroud)\n*注意, typeDeepPartialAny
只是用于类型提示,但它并不完美。从技术上讲,\xc2\xa0type 的逻辑ModifyDeep
允许{a: string}
用对象替换叶节点{a: {b: ... }}
,反之亦然,但是DeepPartialAny
当用平面原语覆盖 an 时会出现如下object
错误:
Type \'number\' has no properties in common with type \'DeepPartialAny<{ a: string; }>\'\n
Run Code Online (Sandbox Code Playgroud)\n但是,您可以安全地忽略该错误(使用/// @ts-ignore
或extends DeepPartialAny
完全删除约束。无论如何,结果类型都会正确计算。
interface Original {\n x: {\n a: string\n b: string\n }\n}\n\ninterface Overrides {\n x: {\n a: never // <- this key will be deleted\n b?: string // <- this will become optional\n }\n}\n\n/* result = {\n x: {\n b?: string\n }\n} */ \n
Run Code Online (Sandbox Code Playgroud)\n
为了缩小属性的类型,简单的extend
作品很完美,如Nitzan 的回答:
interface A {
x: string | number;
}
interface B extends A {
x: number;
}
Run Code Online (Sandbox Code Playgroud)
对于扩大或一般覆盖类型,您可以执行Zskycat 的解决方案:
interface A {
x: string
}
export type B = Omit<A, 'x'> & { x: number };
Run Code Online (Sandbox Code Playgroud)
但是,如果您的接口A
扩展了通用接口,则A
在使用Omit
.
例如
interface A extends Record<string | number, number | string | boolean> {
x: string;
y: boolean;
}
export type B = Omit<A, 'x'> & { x: number };
let b: B = { x: 2, y: "hi" }; // no error on b.y!
Run Code Online (Sandbox Code Playgroud)
原因是,在Omit
内部只检查Exclude<keyof A, 'x'>
键,这string | number
在我们的例子中是通用的。因此,B
将变为{x: number; }
并接受任何类型为 的额外属性number | string | boolean
。
为了解决这个问题,我想出了一个不同的OverrideProps
实用程序类型,如下所示:
type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };
Run Code Online (Sandbox Code Playgroud)
例子:
type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };
interface A extends Record<string | number, number | string | boolean> {
x: string;
y: boolean;
}
export type B = OverrideProps<A, { x: number }>;
let b: B = { x: 2, y: "hi" }; // error: b.y should be boolean!
Run Code Online (Sandbox Code Playgroud)
日期:2021 年 3 月 19 日。我认为最新的打字稿(4.1.2)版本支持文件interface
中的覆盖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" }
Run Code Online (Sandbox Code Playgroud)
您可以使用此类型别名:
type Override<T, K extends { [P in keyof T]: any } | string> =
K extends string
? Omit<T, K>
: Omit<T, keyof K> & K;
Run Code Online (Sandbox Code Playgroud)
并使用类似以下语法:
全球接口
interface IFirst {
username: string;
}
Run Code Online (Sandbox Code Playgroud)
接口override
名称
interface ISecond extends Override<IFirst, 'username'> {
username: number;
}
Run Code Online (Sandbox Code Playgroud)
类型别名override
type IThird = Override<IFirst, { username: boolean }>;
Run Code Online (Sandbox Code Playgroud)
我尝试通过将问题作为提案发送到Typescript Repo来将此别名类型添加为 Typescript 中的内置类型
我创建了这种允许我轻松覆盖嵌套接口的类型:
type ModifyDeep<A extends AnyObject, B extends DeepPartialAny<A>> = {
[K in keyof A]: B[K] extends never
? A[K]
: B[K] extends AnyObject
? ModifyDeep<A[K], B[K]>
: B[K]
} & (A extends AnyObject ? Omit<B, keyof A> : A)
/** Makes each property optional and turns each leaf property into any, allowing for type overrides by narrowing any. */
type DeepPartialAny<T> = {
[P in keyof T]?: T[P] extends AnyObject ? DeepPartialAny<T[P]> : any
}
type AnyObject = Record<string, any>
Run Code Online (Sandbox Code Playgroud)
然后你可以这样使用它:
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> {}
Run Code Online (Sandbox Code Playgroud)
// ModifiedType =
{
a: {
b: string
d: {
e: number
f: number
}
}
b: {
c: number
}
f: number
}
Run Code Online (Sandbox Code Playgroud)
尝试这个:
type Override<T extends object, K extends { [P in keyof T]?: any }> = Omit<T, keyof K> & K;
Run Code Online (Sandbox Code Playgroud)
用法:
type TransformedArticle = Override<Article, { id: string }>;
Run Code Online (Sandbox Code Playgroud)
小智 5
有时,上述解决方案没有帮助。如果出现以下情况,就会发生这种情况。
interface A {
[k: string]: string;
}
interface B extends A {}
type C = Omit<B, 'x'> & { x: number }
Run Code Online (Sandbox Code Playgroud)
C中的x始终为字符串类型。如果您想覆盖例如process.env类型,则这是实际的
为了解决这个问题。您需要通过以下方式重写接口A,以更严格的方式删除键
interface C {
x: number;
}
type ExcludeKeys<Type, Keys> = {
[Property in keyof Type as Exclude<Property, Keys>]: Type[Property];
};
type AA = ExcludeKeys<B, keyof C> & C;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
56555 次 |
最近记录: |