There is a longstanding feature request, microsoft/TypeScript#2225, which asks for the ability to do interface Foo<T> extends T {...} the way you are asking for it. It's not implemented yet (and might never be). Right now you can only make an interface that extends an object type with statically known keys. The unspecified generic type parameter T does not work because the compiler cannot predict what keys it will have.
Note that you cannot fix this by trying to constrain the type parameter like interface Foo<T extends {}> extends T {....}. That will just give you a misleading error message about constraints, as reported in microsoft/TypeScript#57037, and the same problem where T doesn't have statically known keys persists (because T extends U doesn't restrict the keys of T to the keys of U; it might well have more properties).
You should rest assured that an intersection is a reasonable way of achieving this (with the caveat that you will not be warned if your added property conflicts with a property of T, as you noticed). It is the suggested solution in the aforementioned feature request. Additionally, the TypeScript library typings for Object.assign() use an intersection to represent the type of the result of adding properties to an existing object. Therefore, with Confidence<T> defined like
type Confidence<T> = T & {
confidenceLevel: number
}
you can easily write a function that produces one of these like this:
function makeConfidence<T>(x: T, confidenceLevel: number): Confidence<T> {
return Object.assign(x, { confidenceLevel });
}
and use it:
const x = makeConfidence(new Date(), 0.9); // x is a Confidence<Date>;
console.log(x.getFullYear()); // 2020
console.log(x.confidenceLevel); 0.9
Looks good.
Playground link to code