代码重构typescript switch语句

时间:2017-10-19 11:37:08

标签: reactjs typescript

我有以下接口:

export  interface IListItem {
    [key: string]: any;
    id: string;
    title: string;
    modified: Date;
    created: Date;
    modifiedby: string;
    createdby: string;
}

import {IListItem} from "./IListItem";

export interface  IAnnouncementListItem extends IListItem {
    announcementBody: string;
    expiryDate: Date;
}


import {IListItem} from "./IListItem";

export interface IDirectoryListItem extends IListItem {
        firstName: string;
        lastName: string;
        mobileNumber: string;
        internalNumber: string;
}


import {IListItem} from "./IListItem";

export interface  INewsListItem extends IListItem {
    newsheader: string;
    newsbody: string;
    expiryDate: Date;
}

我有以下工厂界面:

import { IListItem } from "./models/IListItem";
import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http";
export  interface IFactory {
    getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[];
}

然后我有以下实现此接口的类

import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http";
import { IWebPartContext } from "@microsoft/sp-webpart-base";
import { IListItem} from "./models/IListItem";
import { IFactory } from "./IFactory";
import { INewsListItem } from "./models/INewsListItem";
import { IDirectoryListItem } from "./models/IDirectoryListItem";
import { IAnnouncementListItem } from "./models/IAnnouncementListItem";

export class ListItemFactory implements IFactory {
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] {
        switch(listName) {
            case "List":
                let items: IListItem[];
                requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
                SPHttpClient.configurations.v1,
                {
                    headers: {
                        "Accept": "application/json;odata=nometadata",
                        "odata-version": ""
                    }
                })
                .then((response: SPHttpClientResponse): Promise<{ value: IListItem[] }> => {
                    return response.json();
                })
                .then((response: { value: IListItem[] }): void => {
                    items= response.value;
                });
                return items;
            case "News":
                let newsitems: INewsListItem[];
                requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
                SPHttpClient.configurations.v1,
                {
                    headers: {
                        "Accept": "application/json;odata=nometadata",
                        "odata-version": ""
                    }
                })
                .then((response: SPHttpClientResponse): Promise<{ value: INewsListItem[] }> => {
                    return response.json();
                })
                .then((response: { value: INewsListItem[] }): void => {
                    newsitems= response.value;
                });
                return newsitems;
            case "Announcements":
                let announcementitems: IAnnouncementListItem[];
                requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
                SPHttpClient.configurations.v1,
                {
                    headers: {
                        "Accept": "application/json;odata=nometadata",
                        "odata-version": ""
                    }
                })
                .then((response: SPHttpClientResponse): Promise<{ value: IAnnouncementListItem[] }> => {
                    return response.json();
                })
                .then((response: { value: IAnnouncementListItem[] }): void => {
                    announcementitems= response.value;
                });
                return announcementitems;
            case "Directory":
                let directoryitems: IDirectoryListItem[];
                requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
                SPHttpClient.configurations.v1,
                {
                    headers: {
                        "Accept": "application/json;odata=nometadata",
                        "odata-version": ""
                    }
                })
                .then((response: SPHttpClientResponse): Promise<{ value: IDirectoryListItem[] }> => {
                    return response.json();
                })
                .then((response: { value: IDirectoryListItem[] }): void => {
                    items= response.value;
                });
                return directoryitems;
            default:
                return null;
        }
      }
}

最后一部分是我不喜欢的部分,我创建了一个switch语句,因为根据选择的列表,返回数组将是不同的类型,IListItem,IAnnouncementListItem,IDirectoryListItem或INewsListItem。

任何使此方法更短的建议&gt;?

第二。我从我的反应组件中这样称呼它:

 // read items using factory method pattern and sets state accordingly
  private readItemsAndSetStatus(): void {
    this.setState({
      status: "Loading all items..."
    });

    const factory: ListItemFactory = new ListItemFactory();
    const items: IListItem[] = factory.getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName);
    const keyPart: string = this.props.listName === "Items" ? "" : this.props.listName;

    // the explicit specification of the type argument `keyof {}` is bad and
    // it should not be required.
    this.setState<keyof {}>({
        status: `Successfully loaded ${items.length} items`,
        ["Details" + keyPart + "ListItemState"] : {
          items,
          columns: [
          ]
        }
      });
  }

但是你可以看到getitems返回一个ListItem数组,这可以改进吗?

1 个答案:

答案 0 :(得分:1)

让我们用这个模拟例子来演示一些技巧......

datasource.xpath(
  'subsystem:connection-url',
  'subsystem' => 'urn:jboss:domain:datasources:1.2')
#⇒ [#<... name="connection-url" namespace=...

过载

您可以使用具有专门签名的方法重载来获取更具体的类型:

class Example {
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] {
        return [];
    }
}

const example = new Example();

// IListItem[]
const news = example.getItems(null, '', 'News');

// IListItem[]
const announcements = example.getItems(null, '', 'Announcements');

策略模式

您可以打破课程并选择合适的课程,而不是在您的big switch语句中包含列表代码......

class Example {
    public getItems(requester: SPHttpClient, siteUrl: string, listName: 'News'): INewsListItem[];
    public getItems(requester: SPHttpClient, siteUrl: string, listName: 'Announcements'): IAnnouncementListItem[];
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[];
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] {
        return [];
    }
}

const example = new Example();

// INewsListItem[]
const news = example.getItems(null, '', 'News');

// IAnnouncementListItem[]
const announcements = example.getItems(null, '', 'Announcements');

然后,您可以将公共代码提取到基类中。代码的每个部分都更小,更易于阅读。还有一些部分,但它们在逻辑上将事物分开。

还有其他一些方法可以实现您的目标,但这些方法将指向您正确的方向。