Skip to content

Force extra property checks if object is explicitly casted or at-least give us a StrictPropertyCheck/Exact type #32537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nojvek opened this issue Jul 24, 2019 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@nojvek
Copy link
Contributor

nojvek commented Jul 24, 2019

TypeScript Version: 3.1.1

Search Terms: extra property checks, explicit cast, exact type

Code

interface Switch {
   on: boolean;
}
const a = <Switch>{on: false, blah: 123}; // no error, ¯\_(ツ)_/¯ 
const b: Switch = {on: false, blah: 123}; // error, may only specify known propery and blah is extra

Expected behavior:
Explicit cast should force extra property checks like the object literal does. I feel like TS team thinks this is intentional and may be a big breaking change.

Alternatively please give us an exact type if possible e.g StrictPropertyCheck<T> so we can do something like const b = <StrictPropertyCheck<SwitchState>>{...}

This stackoverflow thread has some magic vodoo for forcing extra property checks for functions that take arguments. https://stackoverflow.com/questions/54775790/forcing-excess-property-checking-on-variable-passed-to-typescript-function

type StrictPropertyCheck<T, TExpected, TError> = Exclude<keyof T, keyof TExpected> extends never ? {} : TError;

interface Animal {
    speciesName: string
    legCount: number,
}

function serializeBasicAnimalData<T extends Animal>(a: T & StrictPropertyCheck<T, Animal, "Only allowed properties of Animal">) {
    // something
}

Would be nice if we could have a similar mapped type that worked for objects.

Actual behavior:
No error

Playground Link:
https://typescript-play.js.org/#code/JYOwLgpgTgZghgYwgAgJIGED2BbADpkCcAHgGUw5IA+ZAbwChknmBnCyALmXMogG5GzJggIxgAcy4MhM5ABMI8AK4AbMD0gB+Lhv7IA9PrTIA7nHDzFcVevYowmZACMUbKMARgVAT2QIAFhAIANYQcshw4nCgbNx2yLhQmLjQYMAQLIKyTJB4KrzayAAUbLw6dgCUyAC8NObeArIAvlnMSrhyZcWlkACqHV0ACnBQaXAqZHZUVbXIAG6YwHICLfQI+SwsyFh4BERgk7w0wHkQ2PtbGDj4hCS6NNLMuEpOKh7IPRDlvAKtIiBuJSeTBQIpVR6yMD+YAsAB0nxqyAA8k4AFZBMCwuCbCQgIq0JoRLa6AA0yChMNh-zE4lhCmUal0FUazFWQmer3e4ggYD8ogkYLorSEUB5SigICF2Rk9OsjLsUkJ2LivBJwtZrTZbQGkBKdn6nU4yGGo2A40O1HB6qYKPRnixOPEeIpcM+ZM+Bt4zM19FW9FAkFgiBQpBMwDAAV0UuYBC4TkwmBUEHMK3oaw2xLDEf8Oxu+2QEAAHpAQHItrm9ncs5GptGmBy3ghkNzedSBVbpaKwOLJRDpZYGbYumRq-57rQDEYAOqYVThFzIEAeFDAGDk6FbEwg0LhLP+We8ou4RvhvzY3kOTDW-ux5DwFQsCBq-vZV5wfxcACMACYAMxkwxF0caAkigMkAHqAB0AH0ikAEYYKmg-RwKYABaSw4HCEQFGvIQmmfbIWjwtNfTTf5YjgRER3DGsjloW970fMk3w-ZAf1-Jo+EnICCygUCIJg+DEOQ5A1gIWInB0Uco2qOgGPGJjnHyVj2M47iQJBMlsDgXwCB8D4UgQVdfGCEBMBMSVEmSaBfHMedlOQGEC2LKA4CAA

Related Issues:
#9312, #28464

@nojvek nojvek changed the title Force extra property checks if object is explicitly casted or at-least give us an exact type Force extra property checks if object is explicitly casted or at-least give us a StrictPropertyCheck/Exact type Jul 24, 2019
@RyanCavanaugh
Copy link
Member

Sounds like #7481, though it's hard to tell because the example doesn't require a type assertion.

@nojvek
Copy link
Contributor Author

nojvek commented Jul 24, 2019

I'm not sure I understand #7481

As per the typescript play example I would like someway of telling TS to give me stricter property checks that flow through form interface to concrete implementation.

i.e

interface IComponent<State> {
      state: State;
      config: {
          defaultState?: State; // some way to say I want this strict e.g StrictPropertyCheck<State>
          template?: (state: State) => any;
      }
      update: (stateUpdate: Partial<State>) => void;
}

class Component<State> implements IComponent<State> {
    public state: State;

    constructor() {
        this.state = Object.assign({} as State, this.config.defaultState);
    }

    public get config() {
        return {
            defaultState: {} as State,
        }
    }

    update(stateUpdate: Partial<State>) {
        Object.assign(this.state, stateUpdate);
    }
}


interface SwitchState {
    on: boolean;
}

class SwitchComponent extends Component<SwitchState> {
    public get config() {
        return {
            defaultState: {
                on: false,
                blah: 123, // no error, ¯\_(ツ)_/¯  - dead code - I want TS to throw error for extra properties
            },
        }
    }
}

@RyanCavanaugh
Copy link
Member

There's already a way to do that, though - put a return type annotation on config().

#7481 covers the pros and cons of various options here

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jul 24, 2019
@nojvek
Copy link
Contributor Author

nojvek commented Jul 24, 2019

Oh cool, that worked. The question is why is the type not inferred from the base interface. Why do I have to tell TS again ?

image

@typescript-bot
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants