簡體   English   中英

如何根據現場存在縮小對象類型?

[英]How to narrow object type based on field presence?

我有 2 個類似的端點,一個用於獲取列表,另一個用於獲取過濾列表。 現在不可能通過后端的查詢參數將它們合並到一個端點中。 所以我有一個函數可以根據 id 字段的存在來決定使用哪個端點。 問題是我無法獲得正確的類型推斷,無法縮小args

游樂場鏈接

怎么做? 也許,最好使用聯合,但我看不到判別場?

export interface Arguments {
    id?: number;
    token?: string;
    pageSize: number;
}
    
function requestTo1stEndpoint(a: {
    id: number;
    token?: string;
    pageSize: number;
}) {
    return Promise.resolve(1);
}

function requestTo2ndEndpoint(a: {
    token?: string;
    pageSize: number;
}) {
    return Promise.resolve(2);
}
    
async function request(args: Arguments) {
    let fun: typeof requestTo1stEndpoint | typeof requestTo2ndEndpoint
    if (args.id !== undefined) {
        fun = requestTo1stEndpoint
    } else
        fun = requestTo2ndEndpoint
        
    const response = await fun(args)
}

也不起作用:

async function request(args: Arguments) {
    let responsePromise: Response

    // this doesn't work either
    // if ('id' in args) 
    if (args.id !== undefined) {
        // cannot be narrowed
        responsePromise = requestTo1stEndpoint(args)
    } else
        responsePromise = requestTo2ndEndpoint(args)

    const response = await responsePromise
}

您可以使用User Defined Type Guard 和“in” Narrowing來做到這一點。

為了完成這項工作,我們還需要在使用類型保護的iftruefalse包含依賴於args類型的代碼。 這是因為編譯器“知道”如果true部分執行它是Type1 ,而在 else 中它不是Type1

interface Type1{
    id: number;
    token?: string;
    pageSize: number;
}

interface Type2 {
    token?: string;
    pageSize: number;
}

function isType1(x: Type1 | Type2): x is Type1 {
    if ('id' in x) return true;
    return false;
}

function requestTo1stEndpoint(a: Type1) {
    return Promise.resolve(1);
}

function requestTo2ndEndpoint(a: Type2) {
    return Promise.resolve(2);
}

async function request(args: Type1 | Type2) {
    const response = isType1(args) ? await requestTo1stEndpoint(args) : await requestTo2ndEndpoint(args);
}

打字稿游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM