A
arktype•5mo ago
SynthLuvr

Problem with Out type

Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'
Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'
10 Replies
SynthLuvr
SynthLuvr•5mo ago
const transformAmount = (amount: string, problems: Problems): bigint => {
try {
return BigInt(amount);
} catch {
problems.mustBe("a valid number");
return 0n;
}
};

const Test = type({
value: ["string", "|>", transformAmount]
});

const myFunc = () => {
const { data, problems } = Test({});
if (!data || problems) return;

const value: bigint = data.value;
}
const transformAmount = (amount: string, problems: Problems): bigint => {
try {
return BigInt(amount);
} catch {
problems.mustBe("a valid number");
return 0n;
}
};

const Test = type({
value: ["string", "|>", transformAmount]
});

const myFunc = () => {
const { data, problems } = Test({});
if (!data || problems) return;

const value: bigint = data.value;
}
This is working
const transformAmount = (amount: string, problems: Problems): bigint => {
try {
return BigInt(amount);
} catch {
problems.mustBe("a valid number");
return 0n;
}
};

const Test = type({
group: {
nested: {
value: ["string", "|>", transformAmount],
},
},
});

const myFunc = () => {
const { data, problems } = Test({});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
const transformAmount = (amount: string, problems: Problems): bigint => {
try {
return BigInt(amount);
} catch {
problems.mustBe("a valid number");
return 0n;
}
};

const Test = type({
group: {
nested: {
value: ["string", "|>", transformAmount],
},
},
});

const myFunc = () => {
const { data, problems } = Test({});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
Error:
error TS2322: Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'.
error TS2322: Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'.
Adding the type again fixes:
const Test = type({
value: ["string", "|>", transformAmount],
group: {
nested: {
value: ["string", "|>", transformAmount],
},
},
});
const Test = type({
value: ["string", "|>", transformAmount],
group: {
nested: {
value: ["string", "|>", transformAmount],
},
},
});
const Value = ["string", "|>", transformAmount] as const;

const Test = scope({
Value,
group: {
group: {
nested: {
value: Value,
},
},
}
}).compile();

const myFunc = () => {
const { data, problems } = Test.group({});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
const Value = ["string", "|>", transformAmount] as const;

const Test = scope({
Value,
group: {
group: {
nested: {
value: Value,
},
},
}
}).compile();

const myFunc = () => {
const { data, problems } = Test.group({});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
This however doesn't work:
error TS2322: Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'.
error TS2322: Type '(In: string) => Out<bigint>' is not assignable to type 'bigint'.
I don't understand what's going on 😭 The only workaround I can come up with is to add the value twice and then wrap the data I want to parse This is my workaround:
const Value = ["string", "|>", transformAmount] as const;

const Test = type({
Value,
group: {
nested: {
value: Value,
},
},
});

const myFunc = () => {
const mydata = {};
const { data, problems } = Test({...mydata, Value: "0"});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
const Value = ["string", "|>", transformAmount] as const;

const Test = type({
Value,
group: {
nested: {
value: Value,
},
},
});

const myFunc = () => {
const mydata = {};
const { data, problems } = Test({...mydata, Value: "0"});
if (!data || problems) return;

const value: bigint = data.group.nested.value;
};
btw using ArkType version 1.0.29-alpha This also works:
const Test = type({
bla: ["string", "|>", String],
group: {
nested: {
value: Value,
},
},
});
const Test = type({
bla: ["string", "|>", String],
group: {
nested: {
value: Value,
},
},
});
So it seems like any transform needs to be set at the top level first, and then the types can be validated in nested values What I'm doing for now is adding this to the type:
_transform: ["string", "|>", String]
_transform: ["string", "|>", String]
Then created this function to transform the data before passing it to arktype:
const fixArkType = (data: unknown) => {
if (data && typeof data === "object")
(data as { _transform: string })["_transform"] = "";
return data;
};
const fixArkType = (data: unknown) => {
if (data && typeof data === "object")
(data as { _transform: string })["_transform"] = "";
return data;
};
Unsure if this is an arktype bug or if I'm using arktype wrong
ssalbdivad
ssalbdivad•5mo ago
@SynthLuvr Taking a look now. First off I wouldn't recommend transforming and returning both a result 0n and an error- it should be one or the other Have you tried 2.0.0? Just curious in case there is an issue that is likely where I'd fix it
SynthLuvr
SynthLuvr•5mo ago
I haven't taken a look at v2. Is the learning curve steep? I did try upgrading the library but got a bunch of errors upon compilation so there must be breaking changes
ssalbdivad
ssalbdivad•5mo ago
There are breaking changes but all the syntax is the same so they should be easy to fix I summarized the biggest items at the bottom of the announcement Also the morph operator is now => instead of |> and narrow is now : instead of => If you get through those and there are other issues feel free to ask.
SynthLuvr
SynthLuvr•5mo ago
I changed to:
const transformAmount = (amount: string, problems: Problems) => {
try {
return BigInt(amount);
} catch {
return problems.mustBe("a valid number");
}
}
const transformAmount = (amount: string, problems: Problems) => {
try {
return BigInt(amount);
} catch {
return problems.mustBe("a valid number");
}
}
No issue there
ssalbdivad
ssalbdivad•5mo ago
You are right inferring out this nested transform is broken on alpha Sorry about that, I'd recommend upgrading to 2.0 since I'm not publishing new alpha versions any more @SynthLuvr Here's what I'd write on 2.0:
import { type } from "arktype"

const parseBigint = type("string", "=>", (s, ctx) => {
try {
return BigInt(s)
} catch {
return ctx.error("a valid number")
}
})

// or

const parseBigint2 = type("string").pipe((s, ctx) => {
try {
return BigInt(s)
} catch {
return ctx.error("a valid number")
}
})

const Test = type({
group: {
nested: {
value: parseBigint
}
}
})

const myFunc = () => {
const out = Test({})
if (out instanceof type.errors) return

const value: bigint = out.group.nested.value
}
import { type } from "arktype"

const parseBigint = type("string", "=>", (s, ctx) => {
try {
return BigInt(s)
} catch {
return ctx.error("a valid number")
}
})

// or

const parseBigint2 = type("string").pipe((s, ctx) => {
try {
return BigInt(s)
} catch {
return ctx.error("a valid number")
}
})

const Test = type({
group: {
nested: {
value: parseBigint
}
}
})

const myFunc = () => {
const out = Test({})
if (out instanceof type.errors) return

const value: bigint = out.group.nested.value
}
SynthLuvr
SynthLuvr•5mo ago
Thanks. Will try it out It works
ssalbdivad
ssalbdivad•5mo ago
Great! There are a lot of other benefits as well I hope you enjoy it 😊
SynthLuvr
SynthLuvr•5mo ago
I was able to get v1 and v2 to run alongside each other, so will migrate over time
ssalbdivad
ssalbdivad•5mo ago
Just be careful not to use a 1.0 type as a 2.0 def or vice versa Should be a type error anyways since the symbol prop should be unique
Want results from more Discord servers?
Add your server