Sorry for not knowing the exact TS terms for this. But how do I achieve this behavior:
type LocaleErrorMessages = {
required?: () => string | string
email?: () => string | string
passwords?: () => string | string
}
const DanishErrorMessages: LocaleErrorMessages = {
email: () => 'Tjek om du har skrevet din e-mail korrekt',
passwords: () => "Kodeordet lever ikke op til kravene"
}
DanishErrorMessages.email() // do NOT want this to Error
DanishErrorMessages.required() // want this to Error
Playground link here.
CodePudding user response:
use generics
LocaleErrorMessages<T extends object> = {
[k in keyof T]?: Func | string
)
CodePudding user response:
DanishErrorMessages has type LocaleErrorMessages. Therefore, when you try to call its' methods, signatures from LocaleErrorMessages are being used. It means that every of your methods might be undefined. Here's how I solved your problem.
type LocaleErrorMessages = {
required?: () => string | string
email?: () => string | string
passwords?: () => string | string
}
type DanishErrorMessages = LocaleErrorMessages & {
email: () => string | string
passwords: () => string | string
}
const d : DanishErrorMessages = {
email: () => 'Tjek om du har skrevet din e-mail korrekt',
passwords: () => "Kodeordet lever ikke op til kravene"}
d.email() // no error
d.required() // errors
Basically, any variable of type LocaleErrorMessages could only be used with null checks:
const EnglishErrorMessages : LocaleErrorMessages = {email:..., passwords: ...}
if (EnglishErrorMessages.email !== undefined) {
EnglishErrorMessages.email()
}
Try to think how are you goind to use your LocaleErrorMessages variables. If you have way some ts code that uses these methods to retrieve string and generate HTML code, how does it know that this exact locale has defined required
field?
const userLanguageLocale : LocaleErrorMessages = getUserLanguageLocale()
const alertDiv = document.createElement('div')
alertDiv.textContent = userLanguageLocale.required() // compilation error
Therefore, LocaleErrorMessages type is probably useless with this approach. But with null check it makes more sense, since you can change behavior of your page depending on presence of some locales:
const userLanguageLocale : LocaleErrorMessages = getUserLanguageLocale()
const alertDiv = document.createElement('div')
if(userLanguageLocale.required !== undefined) { // if this locale is available
alertDiv.textContent = userLanguageLocale.required() // no compilation error
}
CodePudding user response:
If you have a specific situation you may be able to use Omit
and Required
.
CodePudding user response:
As far as I understand what you're trying to achieve, you should rather make an interface
- ILocaleErrorMessages
that defines what method should be on the object.
DanishErrorMessages
can be a class that implements interface. But throughout the application, you can use interface
as a method/variable signature, but pass proper local language instance.
interface ILocaleErrorMessages {
required?: () => string;
email?: () => string;
passwords?: () => string;
}
class DanishErrorMessages implements ILocaleErrorMessages {
email() { return 'Tjek om du har skrevet din e-mail korrekt'};
passwords() {return "Kodeordet lever ikke op til kravene" };
}
const localErrorMessages: ILocaleErrorMessages = new DanishErrorMessages();
// method `required()` is undefined, but does not break any code
const requiredMessage = localErrorMessages.required?.();
console.log("required message: ", requiredMessage);
const emailMessage = localErrorMessages.email?.();
console.log("email message: ", emailMessage);
const passwordMessage = localErrorMessages.passwords?.();
console.log("password message: ", passwordMessage);
Also, for the cases where function that returns message is undefined
, you can use optional chaining operator?.
- func?.();
TypeScript playground link here.