interface MessageResponseType<R> { responseType: R; } interface MessageVariableType<V> { variableType: V; } type MessageType<R, V = undefined> = MessageResponseType<R> & MessageVariableType<V>; type ResponseOf<T extends MessageResponseType<R>, R = unknown> = T['responseType']; type VariableOf<T extends MessageVariableType<V>, V = unknown> = T['variableType']; // ... 중간 생략 interface Message { currentUser: MessageType<UserObject | undefined>; userList: MessageType<UserObjectPage, UserSearchArgs>; // 이하 생략 } // message는 Message 인터페이스의 필드명으로 제한된다. // variable과 리턴 타입 역시 인터페이스에 설정한 값으로 제한된다. function call<K extends keyof Message, R = ResponseOf<Message[K]>>(message: K, variable: VariableOf<Message[K]>): R { ... } // variable은 optional로 하지 않았기 때문에 이 경우에는 무조건 undefined를 넘겨줘야 한다. // 리턴 값은 UserObject 또는 undefined const user = call('currentUser', undefined); // variable은 UserSearchArgs // 리턴 값은 UserObjectPage const list = call('userList', { ... });
사실 요건 맛뵈기에 불과함