Skip to content

object literal property check inconsistent #16284

Closed
@dlants

Description

@dlants

TypeScript Version: 2.3
Code

type A = {
    a: string
}

let a: A = {
    a: 'a',
    b: 11 // [0] error as expected: object literal can only specify known properties
}

let obj = {
    a: 'a',
    b: 11
}

let a2: A = obj // [1] no error

type B = A | {b: string}

let b: B = {
    a: 'a',
    b: 11 // [2] no error
}

Expected behavior:
There should be a way to make both marks [1] and [2] error, as [0] does.

Actual behavior:
[1] and [2] don't error - and there is no way to structure the code to enforce stricter checks like this.

The behavior in [0] is very fragile, and can lead one to a false sense of security, especially in cases like [2] (where 'b' is present but is of the wrong type). It would be incredibly useful to require the type to be matched exactly.

Motivation:
I think it would be useful to describe the problem I'm trying to solve rather than just proposing a solution.

I am trying to add a layer of type-safety to my db queries. As an example, mongdb has an _id field that is of type ObjectID. It's common to get such an id as part of an http request, in which case it is a string, and forget to convert it into anObjectID before using it in a query (in which case the query returns nothing).

I thought I'd create a union type of possible queries that we might send to a particular collection:

type Query = {
  _id: 'ObjectID'
} | {
  account_id: string
} | {
  _id: 'ObjectID'
  account_id: string
}

declare let findOne: (query: Query) => void

findOne({ _id: "I'm still a string! :(", account_id: "account_id" })

but, this doesn't provide the desired type safety as explained above, and it seems this is not something that TypeScript can help with.

Activity

mhegazy

mhegazy commented on Jun 6, 2017

@mhegazy
Contributor

The first one is the intended design. TypeScript type system is structural, so it is OK to assign a value with more properties to one that expects less. think of var a: Animal = dog; should be allowed. there is one special rule though, for object literals we know there is no way for them to be aliased so any properties on the object, that are not required by the target are flagged as errors (e.g. let a: A = { a: 'a', b: 11 }).

The second issue is tracked by #12745.

mhegazy

mhegazy commented on Aug 17, 2017

@mhegazy
Contributor

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

locked and limited conversation to collaborators on Jun 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @dlants@mhegazy

        Issue actions

          object literal property check inconsistent · Issue #16284 · microsoft/TypeScript