I'm currently looking for two different utility types: one that consists of a subset of a type with matching value types, and another that only requires the keys to exist in another type.
I've devised the following solution, which appears to be acceptable upon initial inspection, but I can't help but wonder if TypeScript (v4.7) already has a built-in feature that accomplishes this.
Update:
The issue I encountered was not related to the type itself, but rather with casting. Using
{ nammme: 'John' as any } as Partial<Person>
works, but I want to avoid it. I need to selectively override the types of certain properties (ideally not all).
// This method is functional...
const fields: Partial<DbUser> = {
organizationId: FieldValue.delete() as any,
groups: FieldValue.delete() as any,
};
return getFirestore()
.collection(constants.dbCollections.users)
.doc(context.auth.uid)
.update(fields);
// This allows for typos...
return getFirestore()
.collection(constants.dbCollections.users)
.doc(context.auth.uid)
.update({
organizationId: FieldValue.delete() as any,
groups: FieldValue.delete() as any,
typoooo: 1 as any,
} as Partial<DbUser>);
Example code snippet
type Person = {
name: string;
age: number;
};
export type KeysIn<T> = {
[key in keyof Partial<T>]: any;
};
export type MustContainKeyButTypeOfKeyCanBeOverwritten<T> = unknown; // ?
// Valid: Key exists in Person
const valid1: KeysIn<Person> = {
name: 0,
};
// Valid: Key exists in Person with matching type
const valid2: Partial<Person> = {
name: '',
};
// Invalid: Key not present in Person
const invalid1: KeysIn<Person> = {
x: true,
};
// Invalid: Key exists in Person but does not match the type
const invalid2: Partial<Person> = {
name: 0,
};
// Invalid: Key not present in Person
const invalid3: Partial<Person> = {
x: true,
};
// Typo present due to cast to any type
const invalid4: KeysIn<Person> = {
namessss: '' as any,
};
const invalid5 = {
namessss: '' as any,
} as Partial<Person>; // Why is this considered valid?
const invalid6 = {
namessss: '' as any,
} as KeysIn<Person>; // Why is this accepted? I require this to be flagged as invalid
const idealExample: MustContainKeyButTypeOfKeyCanBeOverwritten<Person> = {
name: 1 as any, // Type override allowed
aggggggge: 1, // Invalid due to typo
age: '2', // Incorrect type, therefore invalid
};
Is it possible to selectively override specific keys with new types while preventing typos?