Skip to content
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

[3.5.1] Type 'NonNullable<Partial<Config>[T]>' is not assignable to type 'Config[T]' #31675

Closed
kryops opened this issue May 30, 2019 · 1 comment · Fixed by #53112
Closed
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@kryops
Copy link

kryops commented May 30, 2019

TypeScript Version: 3.5.1, 3.6.0-dev.20190530

Search Terms:

partial nonnullable generic mapped strictNullChecks

Code

interface Config {
  string: string
  // There need to be different types in here for the error to occur
  number: number
}

function getConfigOrDefault<T extends keyof Config>(
  userConfig: Partial<Config>,
  key: T,
  defaultValue: Config[T]
): Config[T] {
  const userValue = userConfig[key] // Partial<Config>[T]
  const explicitAssertion = userConfig[key] as Config[T] | undefined // allowed

  // Partial<Config>[T] - already incorrect in 3.4.5?
  const simpleCheck = userValue ? userValue : defaultValue

  // 3.4.5: Config[T]
  // 3.5.1, 3.6.0-dev.20190530: Config[T] | NonNullable<Partial<Config>[T]>
  const assertedCheck = userValue ? userValue! : defaultValue

  return assertedCheck
}

Expected behavior:

No error

Actual behavior:

Type 'Config[T] | NonNullable<Partial<Config>[T]>' is not assignable to type 'Config[T]'.
  Type 'NonNullable<Partial<Config>[T]>' is not assignable to type 'Config[T]'.
    Type 'Partial<Config>[T]' is not assignable to type 'Config[T]'.
      Type 'Partial<Config>' is not assignable to type 'Config'.
        Types of property 'string' are incompatible.
          Type 'string | undefined' is not assignable to type 'string'.
            Type 'undefined' is not assignable to type 'string'.
              Type 'Partial<Config>[T]' is not assignable to type 'string & number'.
                Type 'Partial<Config>[T]' is not assignable to type 'string'.
                  Type 'string | number' is not assignable to type 'Config[T]'.
                    Type 'string' is not assignable to type 'Config[T]'.
                      Type 'string' is not assignable to type 'string & number'.
                        Type 'string' is not assignable to type 'number'.
                          Type 'NonNullable<Partial<Config>[T]>' is not assignable to type 'string & number'.
                            Type 'Partial<Config>[T]' is not assignable to type 'string & number'.
                              Type 'string | number | undefined' is not assignable to type 'string & number'.
                                Type 'undefined' is not assignable to type 'string & number'.
                                  Type 'undefined' is not assignable to type 'string'.
                                    Type 'Partial<Config>[T]' is not assignable to type 'string'.
                                      Type 'string | number' is not assignable to type 'string & number'.
                                        Type 'string' is not assignable to type 'string & number'.
                                          Type 'string' is not assignable to type 'number'.
                                            Type 'NonNullable<Partial<Config>[T]>' is not assignable to type 'string'.
                                              Type 'Partial<Config>[T]' is not assignable to type 'string'.
                                                Type 'string | number | undefined' is not assignable to type 'string'.
                                                  Type 'undefined' is not assignable to type 'string'.
                                                    Type 'string | number' is not assignable to type 'string'.
                                                      Type 'number' is not assignable to type 'string'.ts(2322)

with strictNullChecks: true

Playground Link:

https://www.typescriptlang.org/play/index.html#src=interface%20Config%20%7B%0D%0A%20%20string%3A%20string%0D%0A%20%20%2F%2F%20There%20need%20to%20be%20different%20types%20in%20here%20for%20the%20error%20to%20occur%0D%0A%20%20number%3A%20number%0D%0A%7D%0D%0A%0D%0Afunction%20getConfigOrDefault%3CT%20extends%20keyof%20Config%3E(%0D%0A%20%20userConfig%3A%20Partial%3CConfig%3E%2C%0D%0A%20%20key%3A%20T%2C%0D%0A%20%20defaultValue%3A%20Config%5BT%5D%0D%0A)%3A%20Config%5BT%5D%20%7B%0D%0A%20%20const%20userValue%20%3D%20userConfig%5Bkey%5D%20%2F%2F%20Partial%3CConfig%3E%5BT%5D%0D%0A%20%20const%20explicitAssertion%20%3D%20userConfig%5Bkey%5D%20as%20Config%5BT%5D%20%7C%20undefined%0D%0A%0D%0A%20%20%2F%2F%20Partial%3CConfig%3E%5BT%5D%20-%20already%20incorrect%20in%203.4.5%3F%0D%0A%20%20const%20simpleCheck%20%3D%20userValue%20%3F%20userValue%20%3A%20defaultValue%0D%0A%0D%0A%20%20%2F%2F%203.4.5%3A%20Config%5BT%5D%0D%0A%20%20%2F%2F%203.5.1%2C%203.6.0-dev.20190530%3A%20Config%5BT%5D%20%7C%20NonNullable%3CPartial%3CConfig%3E%5BT%5D%3E%0D%0A%20%20const%20assertedCheck%20%3D%20userValue%20%3F%20userValue!%20%3A%20defaultValue%0D%0A%0D%0A%20%20return%20assertedCheck%0D%0A%7D%0D%0A

(error does not occur there - which TS version does the playground run on?)

Related Issues:

These issues looked similar but were already reported for earlier versions of TypeScript:

#27456
#30706

@wezleytsai
Copy link

My current workaround for this issue:

interface Config {
  string: string
  // There need to be different types in here for the error to occur
  number: number
}

// This compiles just fine in 3.7.2
function getValueOrDefault<K extends keyof T, T>(obj: Partial<T>, key: K, defaultValue: T[K]): T[K] {
    return obj[key] ?? defaultValue;
}

function getConfigOrDefault<T extends keyof Config>(
  userConfig: Partial<Config>,
  key: T,
  defaultValue: Config[T]
): Config[T] {
  // return userConfig[key] ?? defaultValue; // I would expect this to work, as stated above
  return getValueOrDefault(userConfig, key, defaultValue);
}

@RyanCavanaugh RyanCavanaugh added the Rescheduled This issue was previously scheduled to an earlier milestone label Aug 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants