I have a function that resembles the following mock:
// All properties in this type are optional.
interface MyType {
a?: string
}
// The return result type of `cb` is kept as the final result type.
const f = <T extends ReadonlyArray<MyType>>(cb: (() => T)): T => cb()
const myTests1 = f(() => [1, {}]) // no error, but it really should
const myTests2 = f(() => [{}]) // no error
const myTests3 = f(() => [{}] as const) // no error
const myTests4 = f(() => [1]) // error
const myTests5 = f(() => [1, {}] as const) // error
The purpose of the cb
function is to only return items that match the MyType
. The f
function acts as a type-safe data model builder for users to declare complex MyType
with safety.
While TypeScript focuses on duck typing rather than strict JS types (for example, no error when assigning const x: {} = 1
), I noticed my typing issue vanished if any property in MyType
was required.
My questions are:
- Why does the TS compiler accept
myTest1
but notmyTests4
ormyTests5
? - Is there a way to redefine the typing of the above function to prevent users from returning any non-object items in
cb
?