我有一个switch语句,但是每种情况下的内容都非常相似,基本上唯一的区别是REST调用中具有select属性的URL,以及.then,当json结果转换为特定类型的特定集合时。
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 {
// private _listItems: IListItem[];
public getItems(requester: SPHttpClient, siteUrl: string, listName: string): Promise<any[]> {
switch(listName) {
case "GenericList":
let items: IListItem[];
// tslint:disable-next-line:max-line-length
return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`,
SPHttpClient.configurations.v1,
{
headers: {
"Accept": "application/json;odata=nometadata",
"odata-version": ""
}
})
.then((response: SPHttpClientResponse): Promise<{ value: IListItem[] }> => {
return response.json();
})
.then((json: { value: IListItem[] }) => {
console.log(JSON.stringify(json.value));
return items=json.value.map((v,i)=>(
{
// key: v.id,
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title
}
));
});
case "News":
let newsitems: INewsListItem[];
// tslint:disable-next-line:max-line-length
return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Created By,Modified By,newsheader,newsbody,expiryDate`,
SPHttpClient.configurations.v1,
{
headers: {
"Accept": "application/json;odata=nometadata",
"odata-version": ""
}
})
.then((response: SPHttpClientResponse): Promise<{ value: INewsListItem[] }> => {
return response.json();
})
.then((json: { value: INewsListItem[] }) => {
return newsitems=json.value.map((v,i)=>(
{
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
newsheader: v.newsheader,
newsbody: v.newsbody,
expiryDate: v.expiryDate
}
));
});
case "Announcements":
let announcementitems: IAnnouncementListItem[];
return requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Created,Author/Title,Modified,Editor/Title,announcementBody,expiryDate&$expand=Author,Editor`,
SPHttpClient.configurations.v1,
{
headers: {
"Accept": "application/json;odata=nometadata",
"odata-version": ""
}
})
.then((response: SPHttpClientResponse): Promise<{ value: IAnnouncementListItem[] }> => {
return response.json();
})
.then((json: { value: IAnnouncementListItem[] }) => {
return announcementitems=json.value.map((v,i)=>(
{
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
announcementBody: v.announcementBody,
expiryDate: v.expiryDate
}
));
});
case "Directory":
let directoryitems: IDirectoryListItem[];
return 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((json: { value: IDirectoryListItem[] }) => {
return directoryitems=json.value.map((v,i)=>(
{
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
firstName: v.firstName,
lastName: v.lastName,
mobileNumber: v.mobileNumber,
internalNumber: v.internalNumber
}
));
});
default:
break;
}
}
}
更新1
根据答案,我更改了IFactory.ts
import { IListItem } from "./models/IListItem";
import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http";
import { ListItemFactory } from "./ListItemFactory";
export interface IFactory {
getItems<K extends keyof ListItemFactory['handlers']>(requester: SPHttpClient, siteUrl: string, listName: K): Promise<ReturnType<ListItemFactory['handlers'][K]['process']>> ;
//getItems(requester: SPHttpClient, siteUrl: string, listName: string): Promise<any[]>;
}
还有ListItemFactory.ts
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 {
private handlers = {
GenericList : {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`,
async process(result: any) {
const json: { value: IListItem[] } = result;
return json.value.map((v,i)=>({
// key: v.id,
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title
}));
}
},
News: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Created By,Modified By,newsheader,newsbody,expiryDate`,
async process(result: any) {
const json: { value: INewsListItem[] } = result;
return json.value.map((v,i)=>(
{
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
newsheader: v.newsheader,
newsbody: v.newsbody,
expiryDate: v.expiryDate
}
));
}
},
Announcements: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Created,Author/Title,Modified,Editor/Title,announcementBody,expiryDate&$expand=Author,Editor`,
async process(result: any) {
const json: { value: IAnnouncementListItem[] } = result;
return json.value.map((v,i)=>({
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
announcementBody: v.announcementBody,
expiryDate: v.expiryDate
}));
}
},
Directory: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
process(result: any) {
const json: { value: IDirectoryListItem[] } = result;
return json.value.map((v,i)=>({
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
firstName: v.firstName,
lastName: v.lastName,
mobileNumber: v.mobileNumber,
internalNumber: v.internalNumber
}));
}
}
};
public async getItems<K extends keyof ListItemFactory['handlers']>(requester: SPHttpClient, siteUrl: string, listName: K): Promise<ReturnType<ListItemFactory['handlers'][K]['process']>> {
var h = this.handlers[listName];
const response = await requester.get(
h.url(siteUrl, listName),
SPHttpClient.configurations.v1,
{
headers: {
"Accept": "application/json;odata=nometadata",
"odata-version": ""
}
});
var json = response.json();
return h.process(json) as any;
}
}
但是我得到这个错误
[19:42:56] Error - typescript - src/webparts/factoryMethod/components/IFactory.ts(5,122): error TS2304: Cannot find name 'ReturnType'.
[19:42:56] Error - typescript - src/webparts/factoryMethod/components/ListItemFactory.ts(80,135): error TS2304: Cannot find name 'ReturnType'.
[19:42:56] Error - typescript - src/webparts/factoryMethod/components/IFactory.ts(5,122): error TS4057: Return type of method from exported interface has or is using private name 'ReturnType'.
[19:42:56] Error - typescript - src/webparts/factoryMethod/components/ListItemFactory.ts(80,135): error TS4055: Return type of public method from exported class has or is using private name 'ReturnType'.
[19:42:56] Finished subtask 'tslint' after 2.93 s
[19:42:56] Error - 'typescript' sub task errored after 2.06 s
TypeScript error(s) occurred.
我将从每个开关中取出通用部分,然后将不同部分移动到地图对象中。罕见的部分似乎是网址以及如何处理结果。
同样,我们可以使用返回类型和列表类型做得更好。我们将键限制为仅是支持的值之一,并且具有特定于listName
传入的返回类型。
export class ListItemFactory implements IFactory {
handlers = {
GenericList : {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`,
async process(result: any) {
const json: { value: IListItem[] } = result;
return json.value.map((v,i)=>({
// key: v.id,
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title
}));
}
},
News: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Created By,Modified By,newsheader,newsbody,expiryDate`,
async process(result: any) {
const json: { value: INewsListItem[] } = result;
return json.value.map((v,i)=>(
{
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
newsheader: v.newsheader,
newsbody: v.newsbody,
expiryDate: v.expiryDate
}
));
}
},
Announcements: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Created,Author/Title,Modified,Editor/Title,announcementBody,expiryDate&$expand=Author,Editor`,
async process(result: any) {
const json: { value: IAnnouncementListItem[] } = result;
return json.value.map((v,i)=>({
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
announcementBody: v.announcementBody,
expiryDate: v.expiryDate
}));
}
},
Directory: {
url: (siteUrl: string, listName: string) => `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
process(result: any) {
const json: { value: IDirectoryListItem[] } = result;
return json.value.map((v,i)=>({
id: v.Id,
title: v.Title,
created: v.Created,
createdby: v.Author.Title,
modified: v.Modified,
modifiedby: v.Editor.Title,
firstName: v.firstName,
lastName: v.lastName,
mobileNumber: v.mobileNumber,
internalNumber: v.internalNumber
}));
}
}
}
public async getItems<K extends keyof ListItemFactory['handlers']>(requester: SPHttpClient, siteUrl: string, listName: K): Promise<ReturnType<ListItemFactory['handlers'][K]['process']>> {
var h = this.handlers[listName];
const response = await requester.get(
h.url(siteUrl, listName),
SPHttpClient.configurations.v1,
{
headers: {
"Accept": "application/json;odata=nometadata",
"odata-version": ""
}
});
var json = response.json();
return h.process(json) as any;
}
}
let fact = new ListItemFactory();
let requester!: SPHttpClient;
let siteUrl = ''
var genList = fact.getItems(requester, siteUrl, 'GenericList'); // Promise<Promise<{id: any;title: any;created: any;createdby: any;modified: any;modifiedby: any;}[]>>
var dirList = fact.getItems(requester, siteUrl, 'Directory'); // Promise<{id: any;title: any;created: any;createdby: any;modified: any;modifiedby: any;firstName: any;lastName: any;mobileNumber: any;internalNumber: any;}[]>
编辑
关于签名的一点解释getItems
。该方法现在是通用的,其类型参数K
必须是handlers对象的键。通过使用来完成此限制keyof T
,它给出了表示的公钥的类型,T
并且ListItemFactory['handlers']
是类型查询,并给出了handlers
字段的类型,因此我们将其全部得到K extends keyof ListItemFactory['handlers']
。
现在参数listName
只能具有,或的值'GenericList'
,当我们调用方法时,根据传入的值将是表示这些值之一的字符串文字类型。'News'
'Announcements'
'Directory'
K
现在,我们想将返回值绑定getItems
到传入process
函数的返回类型listName
。我们将inlistName
作为字符串文字类型,K
以便获取处理程序的类型,我们可以使用类型查询:ListItemFactory['handlers'][K]
向下钻取以获取process
我们得到的函数的类型ListItemFactory['handlers'][K]['process']
。
要获取此函数类型的返回类型,我们使用内置的条件类型ReturnType<T>
。ReturnType<()=> number>
将是number
,该类型将执行其名称所隐含的含义,如果我们传入一个函数类型,则会得到它的返回值
综上所述,我们得到的返回类型为 Promise<ReturnType<ListItemFactory['handlers'][K]['process']>>
编辑
对于2.4.2,您不能使用条件类型(仅从2.8开始可用)。您可以any
像使用原始代码一样将其用作返回类型(虽然不理想,但这是我们在2.4.2中可以做到的,理想情况下,您应尝试更新到新版本):
public async getItems<K extends keyof ListItemFactory['handlers']>(requester: SPHttpClient, siteUrl: string, listName: K): Promise<any>
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句