我有一个接口(A),而内部有一个接口(B)。接口A用作接口A的数组。
当我更新特定接口A中的接口B时,任何接口A中的所有相同接口B也会被更新。
如果我使用相同的方法但设置了接口A属性,那是正确的。
例如,我编写了一个智能代码。
我们的客户在几分钟之内就吃了一些x产品。我需要知道需要为所有客户服务的农场数量。
作为产品的客户端,eatByMinute和howMany(howMany Client)。 以产品FarmByMinute(多少产品以分钟为单位)作为产品。
我在“客户端接口”中注入“农场接口”以获取大数据对象。我要算出“我需要多少个农场”。
如果我在“ Farm interface”中设置HowManyNeed,则所有“ Client interface”中所有相同的“ Farm interface”采用相同的值。
如果我在“客户端界面”中设置了HowManyFarmNeed,则每个值都是正确的
逻辑是:
Init->开始-> CountFarmNeed->结束
const farms: IFarm[] =
[{
"name": "AppleFarm",
"product": "Apple",
"makeByMinute": 2
}, {
"name": "PerryFarm",
"product": "Perry",
"makeByMinute": 1
}
];
interface IFarm {
name: string,
product: string,
makeByMinute: number,
howManyNeed?: number
}
interface IClient {
name: string,
eatByMinute: number,
whatDoesEat: string,
howMany: number,
farm?: IFarm,
howManyFarmNeed?: number
}
export class Client {
static get(name: string, eatByMinute: number, whatDoesEat: string, howMany: number): IClient {
return {name: name, 'eatByMinute': eatByMinute, 'whatDoesEat': whatDoesEat, 'howMany': howMany}
}
}
export class Farm {
static getByProduct(product: string): IFarm {
//@ts-ignore: array.Find can return "Undefined" BUT function return IFarm. In this exemple is ok
return farms.find((item: IFarm) => item.product == product);
}
}
export default class Problem {
static init() {
let clients: IClient[] = [
Client.get('men', 0.25, 'Apple', 2000),
Client.get('women', 0.30, 'Perry', 1500),
Client.get('dog', 0.25, 'Apple', 3000),
];
clients = this.start(clients);
clients = this.countFarmNeed(clients);
this.end(clients)
}
static start(clients: IClient[]):IClient[] {
for (let c in clients) {
clients[c] = this.loadFarm(clients[c]);
}
return clients
}
static loadFarm(client: IClient): IClient {
client.farm = Farm.getByProduct(client.whatDoesEat);
return client;
}
static countFarmNeed(clients: IClient[]):IClient[] {
for (let c in clients) {
//@ts-ignore: clients[].farm possibly undifined. In this exemple is ok
clients[c].farm.howManyNeed = (clients[c].howMany * clients[c].eatByMinute) / clients[c].farm.makeByMinute;
//@ts-ignore: clients[].farm possibly undifined. In this exemple is ok
clients[c].howManyFarmNeed = (clients[c].howMany * clients[c].eatByMinute) / clients[c].farm.makeByMinute;
}
return clients
}
static end(clients:IClient[]){
console.log(clients)
}
}
我希望
[0].farm.howManyNeed:250;
[1].farm.howManyNeed:450;
[2].farm.howManyNeed:375;
但是实际有:
[0].farm.howManyNeed:375;
[1].farm.howManyNeed:450;
[2].farm.howManyNeed:375;
答案 0 :(得分:0)
您的问题是clients[0].farm
和clients[2].farm
引用相同的对象,因此它们当然将具有相同的howManyNeed
属性值。如果新的countFarmNeed()
具有相同的farm.howManyNeed
,则client
函数将覆盖对farm
的任何更早更改。
如果要具有两个不同的对象,则必须从farm
数组复制farms
对象的副本,而不仅仅是返回它,如:
const Farm = {
getByProduct(product: string): IFarm {
// don't use ts-ignore for trivial type checking like this
const farm = farms.find((item: IFarm) => item.product == product);
// throw a runtime error if you get a problem, and TS understands tihs
if (!farm) throw new Error("Failed to find farm for " + product);
// if you get here, then farm is not undefined
return Object.assign({}, farm); // copy of the farm
}
};
在这里,我使用Object.assign()
将属性从farm
复制到新对象中,然后再返回它。现在您将获得预期的结果。
请注意,其余代码中有一些您可能要解决的麻烦问题:
不要使用// @ts-ignore
comments来抑制简单的类型检查错误。那是过度杀伤力,可能会有奇怪的副作用。如果您所做的只是断言不是undefined
,则可以只使用non-null assertion operator (!
)或继续在运行时检查undefined
并依靠TypeScript的{{3 }},以消除这种可能性。
您似乎正在使用class
仅包含static
个方法,这很奇怪。相反,如果您只是想为一组相关的事物命名,则可以使用普通的旧对象(class Foo {static bar() {}}
变成const Foo = {bar() {}}
)甚至是control flow analysis。 / p>
namespace
or module
使用for...in
循环遍历数组。考虑更常规的迭代方法,例如a generally discouraged。
带有键名的对象通常比参数列表更易于理解。您的Client.get(a,b,c,d)
方法比仅使用{ name: a, eatByMinute: b, whatDoesEat: c, howMany: d }
之类的对象文字要混乱得多。在前者中,开发人员需要记住参数的顺序,而不要为whatDoesEat
传递name
(它们都是string
)。在后者中,无需担心。
我现在就停在那里。希望对您有所帮助。祝你好运!