Cuando ambos usamos una nueva definición de constructor y una definición de constructor normal en ts, ¿cómo implementar la función para hacer que ts pase? Intento usar la función para implementar la definición, pero falló, no puedo entender lo que estoy haciendo
interface Date1 { x: number } interface Date1Constructor { new(s: string): Date1 (n: number): number } // if use class, we can't implement constructor without new // class Date1Imple implements Date1 { // constructor(s:string) { // } // } // or // if use function, how to make ts know what we are doing makes sense // function Date1Imple(param: string): Date1; // function Date1Imple(param: number): number; and // function Date1Imple(param: string | number): Date1 | number { // if(this){ // if (typeof param === 'string') { // return { // x: 2 // } // } // } // if (typeof param === 'number') { // return 2 // } // } function test(a: Date1Constructor) { } test(Date1Imple)La firma de implementación de una función sobrecargada nunca es 100 % compatible con una interpretación estricta de todas las sobrecargas. Dado que la firma de implementación no está incluida en las opciones disponibles en el sitio de llamadas, está bien, y podemos usar un constructor suave as Date1Constructor al final para decir que está bien para TypeScript. Sin embargo, al igual que con cualquier tipo de afirmación, es importante verificar tres veces que su lógica coincida con la afirmación que está haciendo.
En este caso, podemos diferenciar entre una llamada new y una llamada no new a través new.target (en entornos modernos). En una new llamada, solo se permite un argumento de string ; en una llamada no new , solo se permite un number :
const Date1Imple = function (param: string | number) { if (new.target) { if (typeof param !== "string") { throw new Error(`Invalid invocation, 'new Date1Imple(x)' requires a string argument.`); } return { x: 2 }; } if (typeof param !== "number") { throw new Error(`Invalid invocation, 'Date1Imple(x)' requires a number argument.`); } return 2; } as Date1Constructor;Eso produce el comportamiento deseado y ofrece las firmas deseadas:
// Works, typeof `dt` is `string` const dt = new Date1Imple("x"); // Works, typeof `num` is `number` const num = Date1Imple(42); // Fails as expected, the `new` signature doesn't allow a `number` argument const dt2 = new Date1Imple(42); // Fails as expected, the non-`new` signature doesn't allow a `string` argument const num2 = Date1Imple("42");