如何在 Typescript 中扩展匿名类型
How to extend anonymous type in Typescript
在 typescript
中使用匿名类型链接功能时,例如:
let array = [{ seed: 2 }, { seed: 3 }];
array
.map(i => ({ seed: i.seed, square: i.seed * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square}`));
我需要为地图函数定义新的匿名类型。如果我有多个步骤来生成新属性,我最终会编写大量定义代码来获取所有属性。
我可以使用 $.extend
(或 Object.assign
),但那样我将失去智能感知和强类型。
array
.map(i => $.extend(i, { square: i.seed * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square}`));
如何在不重新定义所有属性的情况下扩展匿名对象,同时保持强类型?
怎么样:
interface A {
seed: number;
}
interface B extends A {
square: number;
}
let array: A[] = [{ seed: 2 }, { seed: 3 }];
array
.map<B>(a => {
return { seed: a.seed, square: a.seed * a.seed }
})
.forEach(b => console.log("square for ${b.seed} is ${b.square}"));
或(如果您想匿名):
let array = [{ seed: 2 }, { seed: 3 }];
array
.map<{seed: number, square: number}>(a => {
return { seed: a.seed, square: a.seed * a.seed }
})
.forEach(b => console.log("square for ${b.seed} is ${b.square}"));
(在playground中使用)
我终于找到了解决办法。这可以通过 Intersection Types 来实现。这些可以与匿名类型和 类 一起使用。在下面的示例中,扩展函数将从每个对象和 return 交叉类型的对象复制属性。这将在不丢失智能感知和强类型的情况下减少大量类型定义代码。
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
let array = [{ seed: 2 }, { seed: 3 }];
array
.map(i => extend(i, { square: i.seed * i.seed }))
.map(i => extend(i, { cube: i.square * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square} and cube is ${i.cube}`));
中相同
已实施 f.e。在 core-js and its type definitions return 交叉点类型:
assign<T, U>(target: T, source: U): T & U;
为了添加和更容易理解关于如何使用 intersection types 扩展匿名类型的答案,我做了这个例子来说明它:
interface Animal {
name: string
}
// With named types:
interface Bear extends Animal {
honey: boolean
}
function giveHoney(bear: Bear) {
bear.honey = true;
}
const myBear: Bear = { name: 'Bob', honey: false };
giveHoney(myBear);
// With anonymous types (no need to explicitly define the Bear type):
function giveHoney(bear: Animal & { honey: boolean }) {
bear.honey = true;
}
const myBear = { name: 'Bob', honey: false };
giveHoney(myBear);
在 typescript
中使用匿名类型链接功能时,例如:
let array = [{ seed: 2 }, { seed: 3 }];
array
.map(i => ({ seed: i.seed, square: i.seed * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square}`));
我需要为地图函数定义新的匿名类型。如果我有多个步骤来生成新属性,我最终会编写大量定义代码来获取所有属性。
我可以使用 $.extend
(或 Object.assign
),但那样我将失去智能感知和强类型。
array
.map(i => $.extend(i, { square: i.seed * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square}`));
如何在不重新定义所有属性的情况下扩展匿名对象,同时保持强类型?
怎么样:
interface A {
seed: number;
}
interface B extends A {
square: number;
}
let array: A[] = [{ seed: 2 }, { seed: 3 }];
array
.map<B>(a => {
return { seed: a.seed, square: a.seed * a.seed }
})
.forEach(b => console.log("square for ${b.seed} is ${b.square}"));
或(如果您想匿名):
let array = [{ seed: 2 }, { seed: 3 }];
array
.map<{seed: number, square: number}>(a => {
return { seed: a.seed, square: a.seed * a.seed }
})
.forEach(b => console.log("square for ${b.seed} is ${b.square}"));
(在playground中使用)
我终于找到了解决办法。这可以通过 Intersection Types 来实现。这些可以与匿名类型和 类 一起使用。在下面的示例中,扩展函数将从每个对象和 return 交叉类型的对象复制属性。这将在不丢失智能感知和强类型的情况下减少大量类型定义代码。
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
let array = [{ seed: 2 }, { seed: 3 }];
array
.map(i => extend(i, { square: i.seed * i.seed }))
.map(i => extend(i, { cube: i.square * i.seed }))
.forEach(i => console.log(`square for ${i.seed} is ${i.square} and cube is ${i.cube}`));
中相同
已实施 f.e。在 core-js and its type definitions return 交叉点类型:
assign<T, U>(target: T, source: U): T & U;
为了添加和更容易理解关于如何使用 intersection types 扩展匿名类型的答案,我做了这个例子来说明它:
interface Animal {
name: string
}
// With named types:
interface Bear extends Animal {
honey: boolean
}
function giveHoney(bear: Bear) {
bear.honey = true;
}
const myBear: Bear = { name: 'Bob', honey: false };
giveHoney(myBear);
// With anonymous types (no need to explicitly define the Bear type):
function giveHoney(bear: Animal & { honey: boolean }) {
bear.honey = true;
}
const myBear = { name: 'Bob', honey: false };
giveHoney(myBear);