接口就像他是一个指针一样

时间:2019-06-15 08:12:47

标签: typescript pointers interface

我有一个接口(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;

1 个答案:

答案 0 :(得分:0)

您的问题是clients[0].farmclients[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复制到新对象中,然后再返回它。现在您将获得预期的结果。

Link to code

请注意,其余代码中有一些您可能要解决的麻烦问题:

  • 不要使用// @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)。在后者中,无需担心。

我现在就停在那里。希望对您有所帮助。祝你好运!