microsoft / microsoft/TypeScript

NonNullablePartial type - Partial that doesn't allow explicit null/undefined values

Abierto
#34,902 3 comentarios 12 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Awaiting More Feedback Suggestion
Lenguaje dominante
Go
Estrellas
111k
Forks
14.3k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

Search Terms

partial, nonnullable, required, undefined

Suggestion

This might seem as a duplicate of #13195, but this issue is different in that it doesn't require a possibly breaking change to the TS engine.

It instead gets advantage of a special generic Partial type that doesn't allow explicitly setting null/undefined.

// these of course sadly don't work

type NonNullablePartial<T> = {
    [P in keyof T]?: NonNullable<T[P]>; 
};

type NonNullablePartial<T> = {
  [P in keyof T]?: T[P] extends null | undefined | infer R ? R : T[P];
};

My suggestion adds type safety by guarding against what would likely be an error, which isn't yet possible with current implementation of Partial.

Use Cases

The reason for this issue is the fact that explicit null / undefined prevent the application of a "default" parameter with these patterns

/* In this example
 * default config = { message: 'message' }
 *    user config = { message: undefined }
 */

Object.assign({}, { message: 'message' }, { message: undefined }) // { message: undefined }

const obj = {  // obj = { message: undefined }
  ... { message: 'message' },
  ... { message: undefined }
}

This pattern does not suffer from that and an explicitly set undefined is reassigned with a default param. Though, this pattern is impractical for a large set of config variables.

function f({ message = 'message' } = {}) {
  console.log(message)
}

f({ message: undefined }); // message - correct!
f({ message: null });      // null  -  this makes sense, though not what I am looking for

To put it in other words:
I am using a default config object, which I then need to merge with user config object. I need to prevent the user from possibly mistakenly assigning null/undefined values to parameters which would effectively replace and remove the "default" value.

Examples

export interface ResponseErrorTemplate {
  code: string;
  status: number;
  message: string;
  errorConstructor: typeof ApolloError;
}

export interface ResponseErrorTemplateInput {
  message: string;
  errorConstructor: typeof ApolloError;
}

export type ResponseErrorTemplateGetter = (
  config?: Partial<ResponseErrorTemplateInput> // Here, keep Partial, but prevent null/undefined
) => ResponseErrorTemplate;


const defaultConfig: ResponseErrorTemplateInput = {
  message: 'Not found',
  errorConstructor: ApolloError,
};

export const getNotFoundTemplate: ResponseErrorTemplateGetter = config => ({
  ...defaultConfig,
  ...config, // if user defines message: undefined here, they replace the default 'Not found'
  status: 404,
  code: 'NOT_FOUND',
});

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Empieza revisando las definiciones propuestas de NonNullablePartial y el comportamiento de Partial, mapped-type, null y undefined descrito en el issue. Determina si esto puede expresarse como una funcionalidad del sistema de tipos sin cambiar la salida de JavaScript; se considera terminado cuando existe un diseño concreto y un comportamiento del compilador validado, no solo un ejemplo de un utility-type.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
compilers
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
30/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.