0

I have a type SecretString which can contain any kind of sensitive information that I may handle on my server but which I don't want to accidentally log out. It's a branded string type:

type SecretString = string & {__brand: "secret"}

My logging function takes a string and an object (any, currently) which can contain whatever additional information might be necessary. Is there a way for me to express that second parameter as a type that can be an arbitrary object but will complain if a SecretString is present? Nested checking would be great but I would be happy with first level.

As the SecretString works just like a string, it typically comes from a function like this one:

function decryptString(encryptedString: EncryptedString): SecretString {
  // ...
}

So this is an example of a scenario where I would like an error message:

const keys = decryptString(encryptedKeys);

logger.info('This should not compile!', { 
  valueThatIsOk: 'this is ok', 
  valueThatShouldFail: keys 
});
0

1 Answer 1

1

Recursively is beyond my TypeScript at present, but at the top level a mapped type should work:

type SecretString = string & {__brand: "secret"};

function log<ObjType>(msg: any, obj: ObjType extends SecretString ? never : ObjType) {
    console.log(msg, obj);
}

let x: SecretString = "example" as SecretString;

log("hi", {example: 42});
log("hi", "more info");
log("hi", x);
//        ^−−−−−−−−−−−−−−− error as desired

Playground link

For passing an object instead, it's still the same thing but in an object structure:

function log<ObjType extends object>(
    msg: any,
    obj: {[key in keyof ObjType]: ObjType[key] extends SecretString ? never : ObjType[key]}
) {
    console.log(msg, obj);
}

Playground link

(If you want both, you can combine them in a union.)

Sign up to request clarification or add additional context in comments.

2 Comments

I appreciate this but it's just one level too "top" :-) Even though strings and other primitive values are allowed as the second parameter, I always pass an object. So when I said that nested is not necessary, I meant beyond that level.
@KristianDupont - I've added an example that handles an object and your sample call.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.