React를 어느 정도 사용해 본 적이 있다면 React Query의 queryOptions() 함수를 우연히 접했을 것입니다. 구현은 놀라울 정도로 단순해 보입니다.
export function queryOptions(options: unknown) { return options }
그러나 진짜 마법은 오버로드된 함수 서명에 있습니다. 그렇다면 무엇이 그렇게 특별한가요?
오버로드된 함수가 무엇인지 확실하지 않다면 다음 게시물을 확인하세요. 함수 오버로딩: 여러 함수 서명을 처리하는 방법
React Query의 접근 방식에서 영감을 받아 React 외부에서 작업하는 사람들에게 유용할 수 있는 도우미 함수, 즉 SQL 쿼리와 같은 입력된 쿼리를 생성하는 간단한 방법을 구성했습니다.
export declare const queryParamsSymbol: unique symbol; export declare const queryReturnSymbol: unique symbol; export type Query< TParams extends Record<string, any> = Record<string, any>, TReturn extends Record<string, any> | undefined = undefined, TStatement extends string = string, > = { statement: TStatement; [queryParamsSymbol]: TParams; [queryReturnSymbol]: TReturn; }; export function query< TParams extends Record<string, any> = Record<string, any>, TReturn extends Record<string, any> | undefined = undefined, TStatement extends string = string, >(statement: TStatement): Query<TParams, TReturn> { return { statement: statement } as Query<TParams, TReturn, TStatement>; }
queryOptions()와 유사하게 함수 자체는 꽤 지루합니다. 즉, SQL 문을 가져와 이를 Query 유형의 객체로 래핑한 다음 반환합니다.
다음은 이를 어떻게 부르는지에 대한 간단한 예입니다.
const getUserById = query<{ id: number }, { name: string; email: string }>( 'SELECT name, email FROM users WHERE id = $id', );
두 가지 유형을 일반 매개변수로 전달하는 방법에 주목하세요. 첫 번째는 필수 쿼리 매개변수입니다. 이 경우에는 id입니다. 두 번째는 쿼리의 반환 유형(이름 및 이메일)을 나타냅니다.
내부적으로 query()는 이 두 가지 유형을 반환된 개체에 삽입하여 queryParamsSymbol 및 queryReturnSymbol에 숨겨둡니다. 이러한 기호는 고유 기호로 선언됩니다. 즉, 문자 공간에만 존재하고 트랜스파일된 JavaScript에는 표시되지 않습니다.
저는 이 기호를 사용하여 매개변수와 반환 유형을 임시로 저장하고 필요할 때마다 검색합니다.
type InferQueryParams<TQuery> = TQuery extends Query<infer Params, any> ? Params : never; type UserQueryParams = InferQueryParams<typeof getUserById>; // ^? { id: number } type InferQueryReturn<TQuery> = TQuery extends Query<any, infer Return> ? Return : never; type UserQueryReturn = InferQueryReturn<typeof getUserById>; // ^? { name: string; email: string }
InferQueryParams 및 InferQueryReturn은 매개변수와 반환 유형이 올바르게 추론되고 있는지 확인하는 유틸리티 유형일 뿐입니다. 실제로는 필요하지 않을 수도 있지만 접근 방식을 확인하는 데 유용합니다.
이제 쿼리 개체에 매개변수와 반환 유형을 포함하는 방법을 알았으니 실제로 이러한 쿼리를 어떻게 실행해야 할까요? 입력된 쿼리를 실행할 수 있는 간단한 데이터베이스 클라이언트를 살펴보겠습니다.
class DatabaseClient { async execute< TParams extends Record<string, any>, TReturn extends Record<string, any> >( query: Query<TParams, TReturn>, params: TParams, ): Promise<Array<TReturn>> { // execute the query and return the results // ... return []; } } const db = new DatabaseClient(); // Return type and parameters are inferred from the query object const result = await db.execute(getUserById, { id: 1 }); // ^? { id: number } // ^? Array<{ name: string; email: string }> console.log(result);
이 예에서는 입력된 getUserById 쿼리 객체를 db.execute() 메서드에 전달합니다. Query 유형에는 매개변수와 반환 유형 정보가 모두 포함되어 있으므로 TypeScript는 이를 자동으로 추론합니다. 결과 위로 마우스를 가져가면 이를 쉽게 확인할 수 있으며 TypeScript는 매개변수 객체의 속성으로 id를 제안합니다.
이 TypeScript Playground에서 전체 코드 예제를 찾을 수 있습니다.
위 내용은 고유 기호: 유형 안전을 위한 기호 사용 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!