'Angular EventEmitter with different types
I’m building a checkbox component that can manage three states depending on if a prop is passed.
@Input() value: boolean|null = false;
@Input() triState = false;
@Output() valueChange = new EventEmitter<boolean|null>();
So when I want to manage a 3-state value it works, I pass in a variable of type boolean|null and no problem.
However, if I just want a normal two-state checkbox, I still have to pass in a variable of boolean|null type, which I find annoying for the client code. Passing a boolean value gives me the following error:
(For the value prop)
Type ‘boolean|null’ is not assignable to type ‘boolean’. Type ‘null’ is not assignable to type ‘boolean’.
I know that this is because my EventEmitter emits boolean|null. So what would be the best way to solve this? Is there a way to emit only a boolean if triState is false, and boolean or null if it’s true?
Solution 1:[1]
I see two possible options:
Using types for the EventEmitter generics:
export type TriState = boolean | null; export type DualState = boolean; @Output() stateChange = new EventEmitter<DualState|TriState>();Creating two separate event emitters:
@Output() dualStateChange = new EventEmitter<boolean>(); @Output() triStateChange = new EventEmitter<boolean|null>();- if
triStateistrue, you would emit fromtriStateChange, else fromdualStateChange.
- if
Solution 2:[2]
Easiest (but most errorprone) way is to just reinterpret_cast / std::memcpy if the strings have fixed length:
// no padding
#pragma pack(push, 1)
struct foo {
char str1[12];
uint16_t int1;
char str2[3];
uint32_t int2;
char str3[4];
};
#pragma pack(pop)
void func(const byte* data, const size_t len) {
assert(len == sizeof(foo));
// non owning
const foo* reinterpreted = reinterpret_cast<const foo*>(data);
// owning
foo reinterpreted_val = *reinterpret_cast<const foo*>(data);
foo copied;
memcpy(&copied, data, len);
}
Notes:
- Make sure that you're allowed to use reinterpret_cast https://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing
- if you'd try to use
strlenor another string operation on any of the strings you most likely will get UB, since the strings are not null terminated.
Slightly better approach:
struct foo {
char str1[13];
uint16_t int1;
char str2[4];
uint32_t int2;
char str3[5];
};
void func(const char* data, const size_t len) {
foo f;
memcpy(f.str1, data, 12);
f.str1[12] = '\0';
data+=12;
memcpy(&f.int1, data, sizeof(uint16_t));
data+=sizeof(uint16_t);
memcpy(f.str2, data, 3);
f.str2[3] = '\0';
data+=3;
memcpy(&f.int2, data, sizeof(uint32_t));
data+=sizeof(uint32_t);
memcpy(f.str3, data, 4);
f.str3[4] = '\0';
data+=4;
}
Notes:
- You could combine both approaches to get rid of the pointer arithmetic. That would also account for any padding in your struct you might have.
Solution 3:[3]
- I think the easiest way to do this is to change the string inside the structure to the type of char. Then you can easily copy the objects of this structure according to its size.
- you will have to somehow deal with the byte order on machines with different byte order
struct foo {
char str1[12];
uint16_t int1;
char str2[3];
uint32_t int2;
char str3[5];
};
byte* Encode(foo* p, int Size) {
int FullSize = Size * sizeof(foo);
byte* Returner = new byte[FullSize];
memcpy_s(Returner, FullSize, p, FullSize);
return Returner;
}
foo * func(const byte* data, const size_t len) {
int ArrSize = len/sizeof(foo);
if (!ArrSize || (ArrSize* sizeof(foo)!= len))
return nullptr;
foo* Returner = new foo[ArrSize];
memcpy_s(Returner, len, data, len);
return Returner;
}
int main()
{
const size_t ArrSize = 3;
foo Test[ArrSize] = { {"Test1",1000,"TT",2000,"cccc"},{"Test2",1001,"YY",2001,"vvvv"},{"Test1",1002,"UU",2002,"bbbb"}};
foo* Test1 = nullptr;
byte* Data = Encode(Test, ArrSize);
Test1 = func(Data, ArrSize * sizeof(foo));
if (Test1 == nullptr) {
std::cout << "Error extracting data!" << std::endl;
delete [] Data;
return -1;
}
std::cout << Test1[0].str1 << " " << Test1[1].str1 << " " << Test1[2].str3 << std::endl;
delete [] Data;
delete[] Test1;
return 0;
}
output
Test1 Test2 bbbb
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CCBet |
| Solution 2 | |
| Solution 3 |
