I have the following code snippet:
See it in the Typescript Playground.
// this class is imported by the validator.ts module
class EWC extends Error {
constructor(public message: string, public code: string) {
super(message);
}
}
// The assert function is coming from an external library
// and it has the following signature
interface AssertOtherArg {
name: string;
code: string;
}
function assert<Type>(schema: string, value: unknown, other: AssertOtherArg): asserts value is Type {
throw "unimplemented";
}
// end of assert
// ------- [string-validator.ts] ----------------------------------------------
// import {assert} from "some-lib";
// import EWC from "../util/ewc"
interface OtherInfo {
name: string;
typeErrorCode?: string;
trimBeforeLenghtValidation?: boolean;
minLength?: number;
minLengthErrorCode?: string;
maxLength?: number;
maxLengthErrorCode?: string;
}
function assertValidString(str: unknown, otherInfo: OtherInfo): asserts str is string {
const {name, trimBeforeLenghtValidation = false} = otherInfo;
{
const code = "typeErrorCode" in otherInfo ? otherInfo.typeErrorCode : `invalid_${name.toLocaleUpperCase()}`;
assert<string>("string", str, {name, code});
}
str; // here str: string
if(trimBeforeLenghtValidation) str = str.trim();
str; // here str: unknown! why?
// min length vlaidation
if("minLength" in otherInfo) {
const code = "minLengthErrorCode" in otherInfo ? otherInfo.minLengthErrorCode : `${name.toUpperCase()}_TOO_SHORT`;
const {minLength} = otherInfo;
// the problem is happening here
// Error: Object is of type 'unknown'.(2571)
if(str.length < minLength)
throw new EWC(`"${name}" cannot be shorter than ${minLength} character(s) long!`, code);
}
// maxLength validation
// ...
}
In the assertValidString function, I'm doing an assertion that the argument str is of type string. And you can verify that after the assertion the type of str is indeed string.
assert<string>("string", str, {name, code});
str; // str: string
But the problem occurs after this line:
if(trimBeforeLenghtValidation) str = str.trim();
Now the type of str argument is unknown and it's causing problems further down the line. For example: when I try to access the length property:
// Error: Object is of type 'unknown'.(2571)
if(str.length < minLength)
throw new EWC(`"${name}" cannot be shorter than ${minLength} character(s) long!`, code);
I get the error:
Object is of type 'unknown'.(2571)
I don't understand why this is happening and it seems really weird to me.
I know that I can just apply the any hack as str: any in the function parameter declaration but I really want to understand why this is happening! Please enlighten me about this topic with your Typescript knowledge.
Sorry for my bad English. Thanks in advance <3.