Skip to content

Commit

Permalink
Merge pull request #53 from robertying/discriminate-return-types
Browse files Browse the repository at this point in the history
Discriminate `getAllContents` return type based on input content type
  • Loading branch information
Harry-Chen authored Oct 29, 2023
2 parents 1b914c0 + bdec610 commit ad1a6b0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 28 deletions.
49 changes: 25 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
CredentialProvider,
Fetch,
HelperConfig,
Content,
ContentType,
CourseContent,
CourseInfo,
Expand All @@ -33,6 +32,7 @@ import {
Language,
HomeworkTA,
UserInfo,
ContentTypeMap,
} from './types';
import {
decodeHTML,
Expand Down Expand Up @@ -322,36 +322,37 @@ export class Learn2018Helper {
* Get certain type of content of all specified courses.
* It actually wraps around other `getXXX` functions. You can ignore the failure caused by certain courses.
*/
public async getAllContents(
public async getAllContents<T extends ContentType>(
courseIDs: string[],
type: ContentType,
type: T,
courseType: CourseType = CourseType.STUDENT,
allowFailure = false,
): Promise<CourseContent> {
let fetchFunc: (courseID: string, courseType: CourseType) => Promise<Content[]>;
switch (type) {
case ContentType.NOTIFICATION:
fetchFunc = this.getNotificationList;
break;
case ContentType.FILE:
fetchFunc = this.getFileList;
break;
case ContentType.HOMEWORK:
fetchFunc = this.getHomeworkList;
break;
case ContentType.DISCUSSION:
fetchFunc = this.getDiscussionList;
break;
case ContentType.QUESTION:
fetchFunc = this.getAnsweredQuestionList;
break;
}
) {
const fetchContentForCourse = <T extends ContentType>(type: T, id: string, courseType: CourseType) => {
switch (type) {
case ContentType.NOTIFICATION:
return this.getNotificationList(id, courseType) as Promise<ContentTypeMap[T][]>;
case ContentType.FILE:
return this.getFileList(id, courseType) as Promise<ContentTypeMap[T][]>;
case ContentType.HOMEWORK:
return this.getHomeworkList(id) as Promise<ContentTypeMap[T][]>;
case ContentType.DISCUSSION:
return this.getDiscussionList(id, courseType) as Promise<ContentTypeMap[T][]>;
case ContentType.QUESTION:
return this.getAnsweredQuestionList(id, courseType) as Promise<ContentTypeMap[T][]>;
default:
return Promise.reject({
reason: FailReason.NOT_IMPLEMENTED,
extra: 'Unknown content type',
} as ApiError);
}
};

const contents: CourseContent = {};
const contents: CourseContent<T> = {};

const results = await Promise.allSettled(
courseIDs.map(async (id) => {
contents[id] = await fetchFunc.bind(this)(id, courseType);
contents[id] = await fetchContentForCourse(type, id, courseType);
}),
);

Expand Down
14 changes: 10 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,19 @@ interface IQuestion extends IDiscussionBase {

export type Question = IQuestion;

export type Content = Notification | File | Homework | Discussion | Question;
export type ContentTypeMap = {
[ContentType.NOTIFICATION]: Notification;
[ContentType.FILE]: File;
[ContentType.HOMEWORK]: Homework;
[ContentType.DISCUSSION]: Discussion;
[ContentType.QUESTION]: Question;
};

interface ICourseContent {
[id: string]: Content[];
interface ICourseContent<T extends ContentType> {
[id: string]: ContentTypeMap[T][];
}

export type CourseContent = ICourseContent;
export type CourseContent<T extends ContentType> = ICourseContent<T>;

export interface CalendarEvent {
location: string;
Expand Down

0 comments on commit ad1a6b0

Please sign in to comment.