Skip to content

Instantly share code, notes, and snippets.

@chriswoodle
Created April 12, 2020 06:59
Show Gist options
  • Save chriswoodle/2a8473312c685769999c8c6c1bd9cd4c to your computer and use it in GitHub Desktop.
Save chriswoodle/2a8473312c685769999c8c6c1bd9cd4c to your computer and use it in GitHub Desktop.
class ObjectId { }
namespace Test {
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
type EnhancedOmit<T, K> =
string | number extends keyof T ? T : // T has indexed type e.g. { _id: string; [k: string]: any; } or it is "any"
Omit<T, K>;
type ExtractIdType<TSchema> =
TSchema extends { _id: infer U } // user has defined a type for _id
? {} extends U ? Exclude<U, {}> :
unknown extends U ? ObjectId : U
: ObjectId; // user has not defined _id on schema
// this makes _id optional
type OptionalId<TSchema extends { _id?: any }> =
ObjectId extends TSchema['_id']
// a Schema with ObjectId _id type or "any" or "indexed type" provided
? EnhancedOmit<TSchema, '_id'> & { _id?: ExtractIdType<TSchema> }
// a Schema provided but _id type is not ObjectId
: WithId<TSchema>;
// this adds _id as a required property
type WithId<TSchema> = EnhancedOmit<TSchema, '_id'> & { _id: ExtractIdType<TSchema> };
interface Base {
_id?: ObjectId;
potato: boolean;
}
function insertOne<T extends Base>() {
const rec: Omit<Base, '_id'> = <any>{};
ins<T>(rec); // Problem
ins<Base>(rec); // Good
}
function ins<T>(p: OptionalId<T>) { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment