Typescript: Introduce "extends const" syntax

Created on 1 Aug 2019  路  7Comments  路  Source: microsoft/TypeScript

Imagine we have some interface:

export type User = {
    id: number
    name: string
}

Working as expected:

And we have a function register1 that accepts Partial of this type:

function register1(userProperties: Partial<User>) {
}

register1({
    id: 1,
    name: "Anders",
})

And I want to prevent incident properties passing to that function:

register1({
    id: 1,
    name2: "Anders", // gives me error, great!
})

Not working as expected:

Now imagine I have a register2 function that does the same, and a bit more:

function register2<T extends Partial<User>>(properties: T) {
    // I want to pass T down the road to another function, 
    // and that function returns type-safe result based on actually passed properties
    // let's imagine that function changes given property values to boolean
    return someAnotherFunctionCall<T>(properties)
}

register2({
    id: 1,
}) // returns { id: boolean }

register2({
    id: 1,
    name2: "Anders"
}) // returns { id: boolean } as expected 

Everything works as I need besides one thing - I would like compiler to throw error on name2 property - "missing property name2 on Partial" (to prevent mistakes or refactoring consequences). I understand why I have this error - because T extends Partial<User> means T is extended version of Partial and supposed to have any additional properties. But how can I achieve what I need? Looks like I need a "final" version of Partial. Maybe something like T extends const Partial<User> syntax should be suggested?

It can be a duplicate, I didn't know how to describe problem properly. If it's a new feature please help me to update the issue title. Thanks.

Duplicate

Most helpful comment

It seems like what you really want is exact types, in which case this would be a duplicate of #12936.

All 7 comments

export type User = {
    id: number
    name: string
}
function someAnotherFunctionCall<T extends Partial<User>> (properties : T) {

}
function register2<T extends Partial<User>>(
    properties: (
        T &
        (
            keyof T extends keyof User ?
            unknown :
            ["Extra property not allowed; ", Exclude<keyof T, keyof User>]
        )
    )
) {
    // I want to pass T down the road to another function, 
    // and that function returns type-safe result based on actually passed properties
    // let's imagine that function changes given property values to boolean
    return someAnotherFunctionCall<T>(properties)
}

register2({
    id: 1,
}) // returns { id: boolean }

register2({
    id: 1,
    name2: "Anders"
}) // returns { id: boolean } as expected 

Playground

Not sure if there's another way at the moment.

Maybe someone else will come along and have a better workaround.

It's very rare that these signatures can't be rewritten in a way that works. What's the definition of someAnotherFunctionCall ?

Let me write a very simple implementation of what I have:

export type User = {
    id: number
    name: string
}

export type Selection<T, K extends keyof T> = {
    [P in K]?: boolean
}

export type ModelSelection<T, S extends Selection<T, keyof T>> = {
    [P in keyof T]: S[P] extends true ? T[P] : never
}

function select<T, S extends Selection<T, keyof T>>(model: T, selection: S): ModelSelection<T, S> {
    return undefined as any
}

const user: User = {
    id: 1,
    name: "Anders",
}

const selection = select(user, {
    id: true,
    name2: false // I want to have error here
})

// type of selection is { id: number, name: never } here
// is expected (but really would like not to have "name" in type signature at all, but that's another case)

playground

It seems like what you really want is exact types, in which case this would be a duplicate of #12936.

@fatcerberus yes, it looks so, thanks for reference

@fatcerberus seems like your observation is true once again. The people that want exact types and similar things tend to be people working with data stores

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dlaberge picture dlaberge  路  3Comments

blendsdk picture blendsdk  路  3Comments

siddjain picture siddjain  路  3Comments

jbondc picture jbondc  路  3Comments

manekinekko picture manekinekko  路  3Comments