0

Have a code (typescriptPlayground)

problem is in spread operator. in case of secondObjectFull i have an error. It is ok. firstObject cannot spread to secondFullMapped

But in case of thirdObjectFull i can spread firstObject to thirdFullMapped. I think that because of definition of thirdFullMapped

type thirdMapped = MappedTypeFunc<Omit<third, keyof base>, any>
type thirdFullMapped = baseMapped & thirdMapped;

in this case thirdMapped is empty. I think a problem is becase of this. If thirdMapped is not empty - all work as expected.

How to fix this situation?

Code:

interface base {
    type: string;
    name: string;
    add: string;
}

interface first extends base {
    firstProp: string  
}

interface second extends base {
    secondProp: string    
}

interface third extends base {

}

type MappedTypeFunc<T, U> = {
    [K in keyof T]: (value: T[K], additionalParam?: U) => any;
} 

type baseMapped = MappedTypeFunc<base, any>

type firstMapped = MappedTypeFunc<Omit<first, keyof base>, any>
type firstFullMapped = baseMapped & firstMapped;

type secondMapped = MappedTypeFunc<Omit<second, keyof base>, any>
type secondFullMapped = baseMapped & secondMapped;

type thirdMapped = MappedTypeFunc<Omit<third, keyof base>, any>
type thirdFullMapped = baseMapped & thirdMapped;

const baseObject: baseMapped = {
    type: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    },
    name: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    },
    add: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const firstObject: firstMapped = {
    firstProp: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const secondObject: secondMapped = {
    secondProp: function (value: string, additionalParam?: any) {
        throw new Error("Function not implemented.");
    }
}

const thirdObject: thirdMapped = {}

const firstObjectFull: firstFullMapped = {
    ...baseObject,
    ...firstObject
}
// error - OK
const secondObjectFull: secondFullMapped = {
    ...baseObject,
    ...firstObject
}

// No error on spread  firstObject why???
const thirdObjectFull: thirdFullMapped = {
    ...baseObject,
    ...firstObject
}
1
  • • Excess properties are generally allowed; what do you think needs to be "fixed" here? All of your objects have the properties they are required to have. (Nothing is missing.) If you have a concern about allowing extra properties, please edit to spell that out because it's not clear and TS doesn't work that way. What, exactly, goes wrong if you allow thirdObjectFull to have extra properties? Commented Mar 7 at 20:57

2 Answers 2

1

TS doesn't enforce strict type checking when using spread syntax on object literals when initializing variable. So you can add any additional properties that way. The error on the first object isn't that ...firstObject is used, but secondProp is missing. The third is complete despite of additional props added with ...firstObject so no error.

A first solution that came to mind isn't elegant:

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

thanks. I think this is what i need. Similar solution provide me a DeepSeek ) confused using createStrict function
@AndrewM if this solves your problem don't hesitate to accept it (the gray checkbox), thanks
0

ThirdMapped is {} that is not empty object but object, anything not null or undefined.

You can do something you can try to solve it with: type EmptyObject = Record<string, never>; type NormalizeEmpty = keyof T extends never ? EmptyObject : T;

gl

1 Comment

Welcome to Stack Overflow. This doesn't seem to answer the question; intersecting BaseMapped with EmptyObject would result in something that never accepts any values at all. We want const thirdObjectFull: ThirdFullMapped = { ...baseObject } to succeed. Can you demonstrate with a testable code snippet how this helps with the example code in the question?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.