简体   繁体   中英

Typescript : generic not inferred

I'm new to Typescript, coming from Java/Kotlin. I have this script:

class RequestMessage<ResponseType> {}
class NewOrderRequestMessage extends RequestMessage<OrderFilled | OrderCancelled> {}

async function sendMessage<T>(requestMessage:RequestMessage<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
        // ...
    })
}

(async () => {
    let requestMessage = new NewOrderRequestMessage()
    let result = await sendMessage(requestMessage)
})()

My problem is that result type is inferred as "unknown", while I expected it to be inferred to OrderFilled | OrderCancelled OrderFilled | OrderCancelled , as the parameter of sendMessage is a RequestMessage<OrderFilled | OrderCancelled> RequestMessage<OrderFilled | OrderCancelled>

Typically, in Java/Kotlin, the same logic makes result correctly inferred:

class Promise<T>()

open class RequestMessage<T> {}
class NewOrderRequestMessage : RequestMessage<Int>() {}

fun <T> sendMessage(requestMessage: RequestMessage<T>): Promise<T> {
    return Promise()
}

val requestMessage = NewOrderRequestMessage()
val result = sendMessage(requestMessage)

In this equivalent Kotlin script, result is inferred to Promise<Int> .

Why couldn't it be in Typescript? Due to this unknown type, Typescript doesn't give me error at compilation when sendMessage returns a Promise of another type, giving me weird situations.. I expect response type to be OrderFilled or OrderCancelled, but sendMessage can actually resolve to a promise of a completely unrelated type without having any compilation error, which produces unexpected and unhandled exception at runtime.

TS is not strongly typed language, its type system is about shape only. That said NewOrderRequestMessage is no longer a generic.
If you cast it to RequestMessage<OrderFilled | OrderCancelled> RequestMessage<OrderFilled | OrderCancelled> then inferring will work just fine:

interface OrderFilled {

}

interface OrderCancelled {

}

class RequestMessage<ResponseType> {}
class NewOrderRequestMessage extends RequestMessage<OrderFilled | OrderCancelled> {}
type RequestMessageWithOrder  = RequestMessage<OrderFilled | OrderCancelled>

async function sendMessage<T>(requestMessage:RequestMessage<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
        // ...
    })
}

(async () => {
    let requestMessage: RequestMessageWithOrder = new NewOrderRequestMessage()
    let result = await sendMessage(requestMessage)
})()

Play with the code here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM